AICR-LAGI / data /dynamic.py
Adityadn's picture
Upload 13 files
b13ed37 verified
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)
# Persiapkan semua traces (per hari opsi)
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)
# Tambahkan total
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])
# --- Tabel Transaksi ---
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],
]
# Tambahkan total ke akhir tabel
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
# Tambahkan tabel transaksi emas
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
)
# Harga Beli
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
)
# titik beli
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'Beli ke-{j+1}<br>(Rp {hasil[j]["M"]:,.0f})' if hari <= 80 else
f'B{j+1}'],
textposition=f'{lbp} center',
# textfont=dict(size=10),
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))
# titik jual terakhir
sell_marker = go.Scatter(
x=[dfc.iloc[-1]['lastUpdate']], y=[dfc.iloc[-1]['Harga Jual']],
mode='markers+text',
name='Harga Jual Terakhir',
text=[# 'Jual Sekarang' if hari <= 60 else
'JS'],
textposition=f'{"top" if lbp == "bottom" else lbp} center',
# textfont=dict(size=10),
marker=dict(color='red', size=10),
visible=(hari==d_h) if not isBtn else False
)
# kumpulkan semua trace untuk opsi ini
traces_for_option = [table] + [t1, t2] + markers + [sell_marker]
# simpan ukuran dan rentang untuk opsi ini
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)
# Buat figure subplot dengan 2 baris: [0]=tabel, [1]=grafik
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
# fig.data[idx].visible = (hari == d_h)
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", # tombol ditampilkan ke bawah
buttons=buttons, # isi list tombol kamu
showactive=True,
x=1.033, # posisinya di luar area plot kanan
y=0.5, # mulai dari atas
xanchor="left",
yanchor="top",
pad=dict(r=10, t=10), # padding agar tidak mepet
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)
# fig.show()
print("is_img", is_img)
return fig.to_image("svg").decode() if is_img else html