|
from data.data import *
|
|
|
|
data = ambil_data_emas()
|
|
|
|
def generate(d_h=default_hari, is_img=False, data = ambil_data_emas()):
|
|
fig = go.Figure()
|
|
|
|
df = pd.DataFrame(data['data']['priceList'])[::-1][:max(lhs)]
|
|
df['hargaBeli'] = pd.to_numeric(df['hargaBeli']) * 100
|
|
df['hargaJual'] = pd.to_numeric(df['hargaJual']) * 100
|
|
df['lastUpdate'] = pd.to_datetime(df['lastUpdate'], format='%Y-%m-%d %H:%M:%S')
|
|
df = df.sort_values('lastUpdate').reset_index(drop=True)
|
|
|
|
df.rename(columns={
|
|
"hargaBeli": "Harga Jual",
|
|
"hargaJual": "Harga Beli"
|
|
}, inplace=True)
|
|
|
|
|
|
all_traces = []
|
|
|
|
buttons = []
|
|
slider_steps = []
|
|
|
|
option_sizes = {"btn": [], "ss": []}
|
|
x_rng_list = {"btn": [], "ss": []}
|
|
y_ax_rng_list = {"btn": [], "ss": []}
|
|
|
|
htd_list = {"btn": [], "ss": []}
|
|
freq_list = {"btn": [], "ss": []}
|
|
tickvals_list = {"btn": [], "ss": []}
|
|
|
|
default_idx = {"btn": 0, "ss": 0}
|
|
|
|
slyc_list = {"btn": [], "ss": []}
|
|
|
|
lch = 0
|
|
|
|
def generateTP(i, hari, dfc, x_rng, isBtn):
|
|
nonlocal lch
|
|
|
|
htd = int((x_rng[1] - x_rng[0]).days + 1)
|
|
htd_list["btn" if isBtn else "ss"].append(htd)
|
|
|
|
default_idx["btn" if isBtn else "ss"] = int(i if htd == d_h else default_idx["btn" if isBtn else "ss"])
|
|
|
|
freq = get_freq(htd)
|
|
freq_list["btn" if isBtn else "ss"].append(freq)
|
|
|
|
tickvals = pd.date_range(
|
|
start=x_rng[0].normalize(),
|
|
end=x_rng[1].normalize(),
|
|
freq=freq
|
|
)
|
|
tickvals_list["btn" if isBtn else "ss"].append(tickvals)
|
|
|
|
y_ax_rng_list["btn" if isBtn else "ss"].append(
|
|
[min(dfc["Harga Jual"]) - 100_000, max(dfc["Harga Beli"]) + 100_000]
|
|
)
|
|
|
|
hasil = []
|
|
|
|
mindf = min(dfc["lastUpdate"])
|
|
|
|
isstb = []
|
|
isstbt = []
|
|
validTB = []
|
|
|
|
harga_jual_sekarang = dfc.iloc[-1]['Harga Jual']
|
|
|
|
for k, tb in (enumerate(tanggal_beli)):
|
|
idx = (dfc['lastUpdate'] - tb).abs().idxmin()
|
|
row = dfc.loc[idx]
|
|
harga_beli = row['Harga Beli']
|
|
harga_jual = row['Harga Jual']
|
|
tanggal_beli_riil = row['lastUpdate'].date()
|
|
if tb > mindf:
|
|
validTB.append(tb)
|
|
tanggal_jual = dfc.iloc[-1]['lastUpdate'].date()
|
|
nilai_jual = harga_jual_sekarang * berat_gram[k]
|
|
profit = nilai_jual - uang_awal[k]
|
|
|
|
hasil.append({
|
|
"No": (k - len(isstb) + len(isstbt)) + 1,
|
|
"TglB": tanggal_beli_riil,
|
|
"HBg": harga_beli,
|
|
"g": berat_gram[k],
|
|
"M": uang_awal[k],
|
|
"TglJ": tanggal_jual,
|
|
"HJg": harga_jual,
|
|
"NJ": nilai_jual,
|
|
"PL": profit
|
|
})
|
|
if len(isstb) >=1:
|
|
isstb.append(True)
|
|
isstbt.append(True)
|
|
continue
|
|
|
|
isstb.append(True)
|
|
|
|
|
|
total_berat = sum([h["g"] for h in hasil])
|
|
total_modal = sum([h["M"] for h in hasil])
|
|
total_nilai_jual = sum([h["NJ"] for h in hasil])
|
|
total_profit = sum([h["PL"] for h in hasil])
|
|
|
|
|
|
header = [
|
|
"No",
|
|
"Tgl Beli",
|
|
"Harga Beli/g (Rp)",
|
|
"Berat (g)",
|
|
"Modal (Rp)",
|
|
"Tgl Jual",
|
|
"Harga Jual/g (Rp)",
|
|
f"Nilai Jual Rp{harga_jual_sekarang:,.0f}/g",
|
|
"Profit/Loss (Rp)"
|
|
]
|
|
|
|
profit_loss_values = [row['PL'] for row in hasil] + [total_profit]
|
|
|
|
cells = [
|
|
[row["No"] for row in hasil],
|
|
[row["TglB"].strftime("%Y-%m-%d") for row in hasil],
|
|
[f"Rp {row['HBg']:,.0f}" for row in hasil],
|
|
[f"{row['g']:.4f} g" for row in hasil],
|
|
[f"Rp {row['M']:,.0f}" for row in hasil],
|
|
[row["TglJ"].strftime("%Y-%m-%d") for row in hasil],
|
|
[f"Rp {row['HJg']:,.0f}" for row in hasil],
|
|
[f"Rp {row['NJ']:,.0f}" for row in hasil],
|
|
[f"Rp {PL:,.0f}" for PL in profit_loss_values],
|
|
]
|
|
|
|
|
|
for h, val in enumerate([
|
|
"Total",
|
|
misy*len(cells[1][0])+misy*(round(len(cells[1][0])/7.5)),
|
|
misy*len(cells[2][0])+misy*(round(len(cells[2][0])/7.5)),
|
|
f"{total_berat:.4f} g",
|
|
f"Rp {total_modal:,.0f}",
|
|
misy*len(cells[5][0])+misy*(round(len(cells[5][0])/7.5)),
|
|
misy*len(cells[6][0])+misy*(round(len(cells[6][0])/7.5)),
|
|
f"Rp {total_nilai_jual:,.0f}",
|
|
]):
|
|
cells[h].append(val)
|
|
|
|
lc = len(cells[0]) + 1
|
|
lch = lc if lc > lch else lch
|
|
|
|
profit_loss_header_color = "#b3f3b3" if all(v > 0 for v in profit_loss_values) else (
|
|
"#f7b3b3" if all(v < 0 for v in profit_loss_values) else "#ffd6e7"
|
|
)
|
|
|
|
profit_loss_cell_colors = [
|
|
"#d4fcd4" if v > 0 else "#ffd6e0" if v < 0 else "#ffffff"
|
|
for v in profit_loss_values
|
|
]
|
|
|
|
header_fill_color[-1] = profit_loss_header_color
|
|
cells_fill_color[-1] = profit_loss_cell_colors
|
|
|
|
|
|
table = go.Table(
|
|
header=dict(values=header, fill_color=header_fill_color, align='center'),
|
|
cells=dict(values=cells, fill_color=cells_fill_color, align='center'),
|
|
columnwidth=cwta,
|
|
visible=(hari == d_h) if not isBtn else False
|
|
)
|
|
|
|
|
|
t1 = go.Scatter(
|
|
x=dfc['lastUpdate'], y=dfc['Harga Beli'],
|
|
name='Harga Beli', line=dict(color='green'),
|
|
visible=(hari==d_h) if not isBtn else False
|
|
)
|
|
t2 = go.Scatter(
|
|
x=dfc['lastUpdate'], y=dfc['Harga Jual'],
|
|
name='Harga Jual', line=dict(color='red'),
|
|
visible=(hari==d_h) if not isBtn else False
|
|
)
|
|
|
|
|
|
markers = []
|
|
lbp = None
|
|
|
|
slyc = 3
|
|
|
|
for j, tb in (enumerate(validTB)):
|
|
lbp = "top" if j % 2 == 0 else "bottom"
|
|
markers.append(
|
|
go.Scatter(
|
|
x=[tb], y=[hasil[j]["HBg"]],
|
|
mode='markers+text',
|
|
name=f'Transaksi ke-{j+1} (Beli)',
|
|
text=[
|
|
f'B{j+1}'],
|
|
textposition=f'{lbp} center',
|
|
|
|
marker=dict(color='green', size=10),
|
|
visible=(hari==d_h) if not isBtn else False
|
|
)
|
|
)
|
|
slyc += 1
|
|
|
|
slyc_list["btn" if isBtn else "ss"].append(makeslcy(slyc))
|
|
|
|
|
|
sell_marker = go.Scatter(
|
|
x=[dfc.iloc[-1]['lastUpdate']], y=[dfc.iloc[-1]['Harga Jual']],
|
|
mode='markers+text',
|
|
name='Harga Jual Terakhir',
|
|
text=[
|
|
'JS'],
|
|
textposition=f'{"top" if lbp == "bottom" else lbp} center',
|
|
|
|
marker=dict(color='red', size=10),
|
|
visible=(hari==d_h) if not isBtn else False
|
|
)
|
|
|
|
|
|
traces_for_option = [table] + [t1, t2] + markers + [sell_marker]
|
|
|
|
|
|
option_sizes["btn" if isBtn else "ss"].append(len(traces_for_option))
|
|
x_rng_list["btn" if isBtn else "ss"].append(x_rng)
|
|
|
|
all_traces.append(traces_for_option)
|
|
|
|
rlhs = [i for i in range(7, lhs[7] + 1)]
|
|
|
|
for i, hari in (enumerate(rlhs)):
|
|
cut = df['lastUpdate'].max() - pd.Timedelta(days=hari)
|
|
dfc = df[df['lastUpdate'] > cut]
|
|
x_rng = [dfc['lastUpdate'].min(), dfc['lastUpdate'].max()]
|
|
|
|
generateTP(i, hari, dfc, x_rng, False)
|
|
|
|
for i, hari in (enumerate(lhs[:8])):
|
|
cut = df['lastUpdate'].max() - pd.Timedelta(days=hari)
|
|
dfc = df[df['lastUpdate'] > cut]
|
|
x_rng = [dfc['lastUpdate'].min(), dfc['lastUpdate'].max()]
|
|
|
|
generateTP(i, hari, dfc, x_rng, True)
|
|
|
|
|
|
fig = make_subplots(
|
|
rows=2, cols=1,
|
|
shared_xaxes=False,
|
|
vertical_spacing=0.1,
|
|
row_heights=[(lch if lch >= 5 else 5) / 10, 0.5],
|
|
specs=[[{"type": "table"}], [{"type": "scatter"}]]
|
|
)
|
|
|
|
for traces in all_traces:
|
|
for i, trace in enumerate(traces):
|
|
fig.add_trace(trace, row=1 if i == 0 else 2, col=1)
|
|
|
|
rlhsd = {hari: idx for idx, hari in enumerate(rlhs)}
|
|
|
|
total_traces = sum(option_sizes["ss"]) + sum(option_sizes["btn"])
|
|
|
|
generateLMA = lambda vis, tickvals, x_rng, htd, freq, hari, slyc, y_ax_rng: dict(
|
|
label=f"{hari} Hari",
|
|
method="update",
|
|
args=[
|
|
{"visible": vis},
|
|
{
|
|
"xaxis.tickvals": tickvals,
|
|
"xaxis.range": x_rng,
|
|
"xaxis.autorange": True,
|
|
"title": {
|
|
"text": f'π Tabel dan Grafik Interaktif Harga Emas Pegadaian Digital per Gram ({htd} Hari Terakhir)<br><br><sup>Diambil pada {timestamp_lokal} dengan frekuensi {freq}</sup><br><br>',
|
|
"x": 0.5
|
|
},
|
|
"updatemenus[0].active": lhsd.get(hari, None),
|
|
"sliders[0].active": rlhsd.get(hari, None),
|
|
"sliders[0].y": slyc,
|
|
"yaxis.range": y_ax_rng,
|
|
}
|
|
]
|
|
)
|
|
|
|
start_ss = 0
|
|
lhsd = {hari: idx for idx, hari in enumerate(lhs[:8])}
|
|
|
|
for i, hari in enumerate(tqdm(rlhs)):
|
|
vis = [False] * total_traces
|
|
|
|
cut = df['lastUpdate'].max() - pd.Timedelta(days=hari)
|
|
dfc = df[df['lastUpdate'] > cut]
|
|
|
|
for j in range(option_sizes["ss"][i]):
|
|
idx = start_ss + j
|
|
vis[idx] = True
|
|
fig.data[idx].visible = (hari == d_h)
|
|
|
|
slider_steps.append(generateLMA(
|
|
vis, tickvals_list["ss"][i], x_rng_list["ss"][i], htd_list["ss"][i],
|
|
freq_list["ss"][i], hari, slyc_list["ss"][i], y_ax_rng_list["ss"][i]
|
|
))
|
|
start_ss +=option_sizes["ss"][i]
|
|
|
|
start_btn = sum(option_sizes["ss"])
|
|
|
|
for i, hari in enumerate(tqdm(lhs[:8])):
|
|
vis = [False] * total_traces
|
|
|
|
for j in range(option_sizes["btn"][i]):
|
|
idx = start_btn + j
|
|
vis[idx] = True
|
|
|
|
|
|
buttons.append(generateLMA(
|
|
vis, tickvals_list["btn"][i], x_rng_list["btn"][i], htd_list["btn"][i],
|
|
freq_list["btn"][i], hari, slyc_list["btn"][i], y_ax_rng_list["btn"][i]
|
|
))
|
|
start_btn +=option_sizes["btn"][i]
|
|
|
|
cut = df['lastUpdate'].max() - pd.Timedelta(days=d_h)
|
|
dfc = df[df['lastUpdate'] > cut]
|
|
x_rng = [dfc['lastUpdate'].min(), dfc['lastUpdate'].max()]
|
|
slyc = slyc_list["btn"][default_idx["btn"]]
|
|
|
|
fig.update_xaxes(
|
|
tickvals=tickvals_list["ss"][default_idx["ss"]],
|
|
tickformat="%Y-%m-%d",
|
|
tickangle=-90,
|
|
row=2, col=1
|
|
)
|
|
|
|
fig.update_layout(
|
|
title=dict(
|
|
text=f'π Tabel dan Grafik Interaktif Harga Emas Pegadaian Digital per Gram ({htd_list["btn"][default_idx["btn"]]} Hari Terakhir)<br><br><sup>Diambil pada {timestamp_lokal} dengan frekuensi {freq_list["btn"][default_idx["btn"]]}</sup><br><br>',
|
|
x=0.5
|
|
),
|
|
updatemenus=[dict(
|
|
type="buttons",
|
|
direction="down",
|
|
buttons=buttons,
|
|
showactive=True,
|
|
x=1.033,
|
|
y=0.5,
|
|
xanchor="left",
|
|
yanchor="top",
|
|
pad=dict(r=10, t=10),
|
|
active=default_idx["btn"]
|
|
)],
|
|
sliders=[dict(
|
|
active=default_idx["ss"],
|
|
yanchor="top",
|
|
xanchor="left",
|
|
currentvalue=dict(
|
|
font=dict(size=14),
|
|
prefix="Rentang Hari: ",
|
|
visible=True,
|
|
xanchor="right"
|
|
),
|
|
transition=dict(duration=300, easing="cubic-in-out"),
|
|
pad=dict(b=10),
|
|
len=1.0,
|
|
x=0,
|
|
y=slyc,
|
|
steps=slider_steps
|
|
)],
|
|
xaxis=dict(
|
|
tickvals=tickvals_list["ss"][default_idx["ss"]],
|
|
tickformat="%Y-%m-%d",
|
|
tickangle=-90,
|
|
type='date',
|
|
autorange=True,
|
|
range=x_rng_list["ss"][default_idx["ss"]],
|
|
rangeslider=dict(visible=True),
|
|
),
|
|
yaxis=dict(
|
|
title="Harga per Gram",
|
|
tickprefix="Rp ",
|
|
tickformat=",",
|
|
range=[min(dfc["Harga Jual"]) - 100_000, max(dfc["Harga Beli"]) + 100_000],
|
|
),
|
|
)
|
|
|
|
html = fig.to_html(full_html=False, include_plotlyjs='cdn')
|
|
uf("grafik/pegadaian_digital/interaktif.html", html)
|
|
|
|
|
|
|
|
print("is_img", is_img)
|
|
|
|
return fig.to_image("svg").decode() if is_img else html
|
|
|