113 lines
3.8 KiB
Python
113 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
import pandas as pd
|
|
import plotly.graph_objects as go
|
|
|
|
|
|
def add_example_trade_markers(fig: go.Figure, example_trades: pd.DataFrame) -> None:
|
|
if example_trades.empty:
|
|
return
|
|
|
|
long_entries = example_trades[example_trades["direction"] == "LONG"]
|
|
short_entries = example_trades[example_trades["direction"] == "SHORT"]
|
|
win_exits = example_trades[example_trades["outcome"] == "Win"]
|
|
non_win_exits = example_trades[example_trades["outcome"] != "Win"]
|
|
|
|
if not long_entries.empty:
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
x=long_entries["entry_timestamp"],
|
|
y=long_entries["entry_price"],
|
|
mode="markers",
|
|
name="Example Entry (Long)",
|
|
marker=dict(color="#1565C0", size=9, symbol="circle"),
|
|
),
|
|
row=1,
|
|
col=1,
|
|
)
|
|
if not short_entries.empty:
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
x=short_entries["entry_timestamp"],
|
|
y=short_entries["entry_price"],
|
|
mode="markers",
|
|
name="Example Entry (Short)",
|
|
marker=dict(color="#EF6C00", size=9, symbol="diamond"),
|
|
),
|
|
row=1,
|
|
col=1,
|
|
)
|
|
if not win_exits.empty:
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
x=win_exits["exit_timestamp"],
|
|
y=win_exits["exit_price"],
|
|
mode="markers",
|
|
name="Example Exit (Win)",
|
|
marker=dict(color="#2E7D32", size=10, symbol="x"),
|
|
),
|
|
row=1,
|
|
col=1,
|
|
)
|
|
if not non_win_exits.empty:
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
x=non_win_exits["exit_timestamp"],
|
|
y=non_win_exits["exit_price"],
|
|
mode="markers",
|
|
name="Example Exit (Loss/Flat)",
|
|
marker=dict(color="#C62828", size=10, symbol="x"),
|
|
),
|
|
row=1,
|
|
col=1,
|
|
)
|
|
|
|
|
|
def highlight_selected_trade(
|
|
fig: go.Figure,
|
|
analyzed: pd.DataFrame,
|
|
selected_trade: pd.Series | None,
|
|
focus_chart_on_selected_example: bool,
|
|
) -> None:
|
|
if selected_trade is None:
|
|
return
|
|
|
|
selected_entry_ts = pd.Timestamp(selected_trade["entry_timestamp"])
|
|
selected_exit_ts = pd.Timestamp(selected_trade["exit_timestamp"])
|
|
selected_entry_price = float(selected_trade["entry_price"])
|
|
selected_exit_price = float(selected_trade["exit_price"])
|
|
selected_direction = str(selected_trade["direction"])
|
|
selected_outcome = str(selected_trade["outcome"])
|
|
|
|
path_color = "#43A047" if selected_outcome == "Win" else ("#EF6C00" if selected_outcome == "Flat" else "#E53935")
|
|
window_fill = "#BBDEFB" if selected_direction == "LONG" else "#FFE0B2"
|
|
|
|
fig.add_vrect(
|
|
x0=selected_entry_ts,
|
|
x1=selected_exit_ts,
|
|
fillcolor=window_fill,
|
|
opacity=0.18,
|
|
line_width=0,
|
|
row=1,
|
|
col=1,
|
|
)
|
|
fig.add_trace(
|
|
go.Scatter(
|
|
x=[selected_entry_ts, selected_exit_ts],
|
|
y=[selected_entry_price, selected_exit_price],
|
|
mode="lines+markers",
|
|
name="Selected Example Path",
|
|
line=dict(color=path_color, width=3, dash="dot"),
|
|
marker=dict(color=path_color, size=11, symbol="star"),
|
|
),
|
|
row=1,
|
|
col=1,
|
|
)
|
|
|
|
if focus_chart_on_selected_example:
|
|
entry_pos = int(analyzed.index.get_indexer([selected_entry_ts], method="nearest")[0])
|
|
exit_pos = int(analyzed.index.get_indexer([selected_exit_ts], method="nearest")[0])
|
|
left_pos = max(0, min(entry_pos, exit_pos) - 4)
|
|
right_pos = min(len(analyzed) - 1, max(entry_pos, exit_pos) + 4)
|
|
fig.update_xaxes(range=[analyzed.index[left_pos], analyzed.index[right_pos]])
|