From fbff9c37a22900089d2077255cd6d57e17e72462 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Tue, 4 Feb 2025 21:49:35 +0200 Subject: [PATCH] Html (kind of) chart --- crypto/brian/index-deep-new.py | 126 ++++++++++++++++++++++++--------- crypto/brian/live_chart.html | 32 +++++++++ 2 files changed, 125 insertions(+), 33 deletions(-) create mode 100644 crypto/brian/live_chart.html diff --git a/crypto/brian/index-deep-new.py b/crypto/brian/index-deep-new.py index 5a10fcc..3107b6b 100644 --- a/crypto/brian/index-deep-new.py +++ b/crypto/brian/index-deep-new.py @@ -215,6 +215,92 @@ def load_best_checkpoint(model, best_dir=BEST_DIR): model.load_state_dict(checkpoint["model_state_dict"]) return checkpoint +# --- Live HTML Chart Update --- +def update_live_html(candles, trade_history, epoch): + """ + Generate a chart image with buy/sell markers and a dotted line between open and close, + then embed it in a simple HTML page that auto-refreshes. + """ + from io import BytesIO + import base64 + + fig, ax = plt.subplots(figsize=(12, 6)) + update_live_chart(ax, candles, trade_history) + ax.set_title(f"Live Trading Chart - Epoch {epoch}") + buf = BytesIO() + fig.savefig(buf, format='png') + plt.close(fig) + buf.seek(0) + image_base64 = base64.b64encode(buf.getvalue()).decode('utf-8') + html_content = f""" + + + + + + Live Trading Chart - Epoch {epoch} + + + +
+

Live Trading Chart - Epoch {epoch}

+ Live Chart +
+ + +""" + with open("live_chart.html", "w") as f: + f.write(html_content) + print("Updated live_chart.html.") + +# --- Chart Drawing Helpers (used by both live preview and HTML update) --- +def update_live_chart(ax, candles, trade_history): + """ + Plot the chart with close price, buy and sell markers, and dotted lines joining buy/sell entry/exit. + """ + ax.clear() + close_prices = [candle["close"] for candle in candles] + x = list(range(len(close_prices))) + ax.plot(x, close_prices, label="Close Price", color="black", linewidth=1) + buy_label_added = False + sell_label_added = False + for trade in trade_history: + in_idx = trade["entry_index"] + out_idx = trade["exit_index"] + in_price = trade["entry_price"] + out_price = trade["exit_price"] + if not buy_label_added: + ax.plot(in_idx, in_price, marker="^", color="green", markersize=10, label="BUY") + buy_label_added = True + else: + ax.plot(in_idx, in_price, marker="^", color="green", markersize=10) + if not sell_label_added: + ax.plot(out_idx, out_price, marker="v", color="red", markersize=10, label="SELL") + sell_label_added = True + else: + ax.plot(out_idx, out_price, marker="v", color="red", markersize=10) + ax.plot([in_idx, out_idx], [in_price, out_price], linestyle="dotted", color="blue") + ax.set_xlabel("Candle Index") + ax.set_ylabel("Price") + ax.legend() + ax.grid(True) + # --- Backtest Environment --- class BacktestEnvironment: def __init__(self, candles_dict, base_tf, timeframes): @@ -284,7 +370,7 @@ class BacktestEnvironment: return len(self.candles_dict[self.base_tf]) # --- Enhanced Training Loop --- -def train_on_historical_data(env, model, device, args, start_epoch, optimizer, scheduler): +def train_on_historical_data(env, model, device, args, start_epoch, optimizer, scheduler, base_candles): for epoch in range(start_epoch, args.epochs): state = env.reset() total_loss = 0 @@ -309,40 +395,13 @@ def train_on_historical_data(env, model, device, args, start_epoch, optimizer, s break state = next_state scheduler.step() - epoch_loss = total_loss/len(env) + epoch_loss = total_loss / len(env) print(f"Epoch {epoch+1} Loss: {epoch_loss:.4f}") save_checkpoint(model, optimizer, epoch, total_loss) + # Update the live HTML file with the current epoch chart + update_live_html(base_candles, env.trade_history, epoch+1) -# --- Live Plotting Functions --- -def update_live_chart(ax, candles, trade_history): - ax.clear() - close_prices = [candle["close"] for candle in candles] - x = list(range(len(close_prices))) - ax.plot(x, close_prices, label="Close Price", color="black", linewidth=1) - buy_label_added = False - sell_label_added = False - for trade in trade_history: - in_idx = trade["entry_index"] - out_idx = trade["exit_index"] - in_price = trade["entry_price"] - out_price = trade["exit_price"] - if not buy_label_added: - ax.plot(in_idx, in_price, marker="^", color="green", markersize=10, label="BUY") - buy_label_added = True - else: - ax.plot(in_idx, in_price, marker="^", color="green", markersize=10) - if not sell_label_added: - ax.plot(out_idx, out_price, marker="v", color="red", markersize=10, label="SELL") - sell_label_added = True - else: - ax.plot(out_idx, out_price, marker="v", color="red", markersize=10) - ax.plot([in_idx, out_idx], [in_price, out_price], linestyle="dotted", color="blue") - ax.set_title("Live Trading Chart") - ax.set_xlabel("Candle Index") - ax.set_ylabel("Price") - ax.legend() - ax.grid(True) - +# --- Live Plotting Functions (For live mode) --- def live_preview_loop(candles, env): plt.ion() fig, ax = plt.subplots(figsize=(12, 6)) @@ -406,7 +465,8 @@ async def main(): print("Loaded optimizer state from checkpoint.") else: print("No valid optimizer state found in checkpoint; starting fresh optimizer state.") - train_on_historical_data(env, model, device, args, start_epoch, optimizer, scheduler) + # Pass base candles from the base timeframe for HTML chart updates. + train_on_historical_data(env, model, device, args, start_epoch, optimizer, scheduler, candles_dict[base_tf]) elif args.mode == 'live': load_best_checkpoint(model) diff --git a/crypto/brian/live_chart.html b/crypto/brian/live_chart.html new file mode 100644 index 0000000..9cacafb --- /dev/null +++ b/crypto/brian/live_chart.html @@ -0,0 +1,32 @@ + + + + + + + Live Trading Chart - Epoch 9 + + + +
+

Live Trading Chart - Epoch 9

+ Live Chart +
+ +