修复k线图开平仓
This commit is contained in:
@@ -642,6 +642,15 @@ def _local_input_datetime_to_ms(dt_text):
|
||||
return None
|
||||
|
||||
|
||||
def _marker_tag_label(tag):
|
||||
t = str(tag or "").strip().upper()
|
||||
if t == "ENTRY":
|
||||
return "开仓"
|
||||
if t == "EXIT":
|
||||
return "平仓"
|
||||
return str(tag or "")
|
||||
|
||||
|
||||
def _pick_marker_point(rows, target_ts_ms, target_price=None):
|
||||
if not rows or target_ts_ms is None:
|
||||
return None, None
|
||||
@@ -696,7 +705,7 @@ def _render_candles_subplot(rows, title, width, height, bg_rgb=(255, 255, 255),
|
||||
continue
|
||||
if idx < 0 or idx >= n:
|
||||
continue
|
||||
marker_by_idx[idx] = mp
|
||||
marker_by_idx.setdefault(idx, []).append(mp)
|
||||
|
||||
x0 = pad_l
|
||||
for i, r in enumerate(rows):
|
||||
@@ -723,27 +732,29 @@ def _render_candles_subplot(rows, title, width, height, bg_rgb=(255, 255, 255),
|
||||
draw.rectangle((left, top, left + body_w, bot), fill=(255, 255, 255), outline=edge_color, width=1)
|
||||
else:
|
||||
draw.rectangle((left, top, left + body_w, bot), fill=edge_color, outline=edge_color, width=1)
|
||||
if i in marker_by_idx:
|
||||
mp = marker_by_idx[i]
|
||||
for j, mp in enumerate(marker_by_idx.get(i, [])):
|
||||
tag = str(mp.get("tag") or "")
|
||||
label = _marker_tag_label(tag)
|
||||
m_price = float(mp.get("price") or r["c"])
|
||||
y_m = pad_t + int((hi - m_price) / (hi - lo) * plot_h)
|
||||
y_m = max(pad_t + 4, min(pad_t + plot_h - 4, y_m))
|
||||
x_off = (j - (len(marker_by_idx[i]) - 1) / 2.0) * 14
|
||||
x_draw = int(x_mid + x_off)
|
||||
if tag == "ENTRY":
|
||||
m_color = (0, 195, 95)
|
||||
tri = [(x_mid, y_m - 20), (x_mid - 9, y_m - 4), (x_mid + 9, y_m - 4)]
|
||||
tri = [(x_draw, y_m - 20), (x_draw - 9, y_m - 4), (x_draw + 9, y_m - 4)]
|
||||
text_y = y_m - 36
|
||||
else:
|
||||
m_color = (235, 65, 65)
|
||||
tri = [(x_mid, y_m + 20), (x_mid - 9, y_m + 4), (x_mid + 9, y_m + 4)]
|
||||
tri = [(x_draw, y_m + 20), (x_draw - 9, y_m + 4), (x_draw + 9, y_m + 4)]
|
||||
text_y = y_m + 12
|
||||
draw.ellipse((x_mid - 5, y_m - 5, x_mid + 5, y_m + 5), fill=m_color, outline=(255, 255, 255), width=1)
|
||||
draw.ellipse((x_draw - 5, y_m - 5, x_draw + 5, y_m + 5), fill=m_color, outline=(255, 255, 255), width=1)
|
||||
draw.polygon(tri, fill=m_color)
|
||||
draw.line((x_mid, y_m, x_mid, y_m - 16 if tag == "ENTRY" else y_m + 16), fill=m_color, width=3)
|
||||
draw.line((x_draw, y_m, x_draw, y_m - 16 if tag == "ENTRY" else y_m + 16), fill=m_color, width=3)
|
||||
if font:
|
||||
draw.text((x_mid + 8, text_y), tag, fill=m_color, font=font)
|
||||
draw.text((x_draw + 8, text_y), label, fill=m_color, font=font)
|
||||
else:
|
||||
draw.text((x_mid + 8, text_y), tag, fill=m_color)
|
||||
draw.text((x_draw + 8, text_y), label, fill=m_color)
|
||||
x0 = x1
|
||||
|
||||
if len(marker_points or []) >= 2:
|
||||
@@ -853,6 +864,7 @@ def generate_multi_timeframe_chart_png(
|
||||
end_ts_ms = int(marker_payload.get("exit_ts_ms") or marker_payload.get("entry_ts_ms") or 0) or None
|
||||
except (TypeError, ValueError):
|
||||
end_ts_ms = None
|
||||
default_marker_tfs = {str(t).strip().lower() for t in timeframes}
|
||||
for tf in timeframes:
|
||||
try:
|
||||
ohlcv = _fetch_ohlcv_ending_at(exchange_symbol, tf, limit, end_ts_ms)
|
||||
@@ -864,7 +876,13 @@ def generate_multi_timeframe_chart_png(
|
||||
title = f"{title_prefix} | {tf} x{len(rows)}"
|
||||
points = []
|
||||
tf_key = str(tf).strip().lower()
|
||||
marker_tfs = {str(x).strip().lower() for x in (marker_timeframes or []) if str(x).strip()}
|
||||
if marker_payload:
|
||||
if marker_timeframes:
|
||||
marker_tfs = {str(x).strip().lower() for x in marker_timeframes if str(x).strip()}
|
||||
else:
|
||||
marker_tfs = default_marker_tfs
|
||||
else:
|
||||
marker_tfs = set()
|
||||
if marker_payload and tf_key in marker_tfs:
|
||||
entry_idx, entry_price = _pick_marker_point(rows, marker_payload.get("entry_ts_ms"), marker_payload.get("entry_price"))
|
||||
exit_idx, exit_price = _pick_marker_point(rows, marker_payload.get("exit_ts_ms"), marker_payload.get("exit_price"))
|
||||
@@ -922,7 +940,26 @@ def generate_multi_timeframe_chart_png(
|
||||
return fname
|
||||
|
||||
|
||||
def generate_order_open_chart(exchange_symbol, title_prefix, timeframes=None, limit=None):
|
||||
def generate_order_open_chart(
|
||||
exchange_symbol,
|
||||
title_prefix,
|
||||
timeframes=None,
|
||||
limit=None,
|
||||
opened_at_ms=None,
|
||||
entry_price=None,
|
||||
):
|
||||
marker_payload = None
|
||||
if opened_at_ms:
|
||||
marker_payload = {
|
||||
"entry_ts_ms": opened_at_ms,
|
||||
"exit_ts_ms": None,
|
||||
"entry_price": entry_price,
|
||||
"exit_price": None,
|
||||
}
|
||||
marker_tfs = (
|
||||
{x.strip().lower() for x in (timeframes or ORDER_CHART_TFS) if x and str(x).strip()}
|
||||
or {"5m", "15m", "1h", "4h"}
|
||||
)
|
||||
return generate_multi_timeframe_chart_png(
|
||||
exchange_symbol,
|
||||
title_prefix,
|
||||
@@ -931,6 +968,8 @@ def generate_order_open_chart(exchange_symbol, title_prefix, timeframes=None, li
|
||||
out_dir=ORDER_CHART_DIR,
|
||||
filename=None,
|
||||
filename_prefix="order",
|
||||
marker_payload=marker_payload,
|
||||
marker_timeframes=marker_tfs,
|
||||
)
|
||||
|
||||
|
||||
@@ -6572,7 +6611,12 @@ def add_order():
|
||||
if make_order_chart and ORDER_CHART_ENABLED:
|
||||
try:
|
||||
title_prefix = f"{symbol} {direction} #{new_order_id}"
|
||||
chart_name = generate_order_open_chart(exchange_symbol, title_prefix)
|
||||
chart_name = generate_order_open_chart(
|
||||
exchange_symbol,
|
||||
title_prefix,
|
||||
opened_at_ms=opened_at_ms,
|
||||
entry_price=trigger_price,
|
||||
)
|
||||
if chart_name:
|
||||
chart_url = f"/static/images/order_charts/{chart_name}"
|
||||
except Exception:
|
||||
@@ -7147,10 +7191,9 @@ def add_journal():
|
||||
symbol_guess = normalize_symbol_input(coin) or coin
|
||||
exchange_symbol = normalize_exchange_symbol(symbol_guess)
|
||||
title_prefix = f"{symbol_guess} journal {entry_id[:8]}"
|
||||
close_ms = _local_input_datetime_to_ms(d.get("close_datetime"))
|
||||
marker_payload = {
|
||||
"exit_ts_ms": close_ms,
|
||||
"entry_ts_ms": close_ms,
|
||||
"entry_ts_ms": _local_input_datetime_to_ms(d.get("open_datetime")),
|
||||
"exit_ts_ms": _local_input_datetime_to_ms(d.get("close_datetime")),
|
||||
"entry_price": d.get("entry_price_hint"),
|
||||
"exit_price": None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user