Fix embed date filter reload and classify profitable stops as trailing TP.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -193,6 +193,7 @@ from history_window_lib import (
|
|||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
utc_window_to_utc_sql_strings,
|
utc_window_to_utc_sql_strings,
|
||||||
)
|
)
|
||||||
|
from trade_result_lib import normalize_result_with_pnl
|
||||||
|
|
||||||
def load_env_file(path):
|
def load_env_file(path):
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
@@ -2132,6 +2133,10 @@ def to_effective_trade_dict(row):
|
|||||||
item["display_pnl_source"] = "reviewed"
|
item["display_pnl_source"] = "reviewed"
|
||||||
else:
|
else:
|
||||||
item["display_pnl_source"] = "local"
|
item["display_pnl_source"] = "local"
|
||||||
|
item["effective_result"] = normalize_result_with_pnl(
|
||||||
|
item.get("effective_result"),
|
||||||
|
item.get("effective_pnl_amount"),
|
||||||
|
)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
@@ -2573,19 +2578,6 @@ def calc_actual_rr(pnl_amount, risk_amount):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def normalize_result_with_pnl(result, pnl_amount):
|
|
||||||
"""
|
|
||||||
触发“止损”但实际已盈利时,归类为保本止盈,避免语义混淆。
|
|
||||||
"""
|
|
||||||
if result == "止损":
|
|
||||||
try:
|
|
||||||
if float(pnl_amount or 0) > 0:
|
|
||||||
return "保本止盈"
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
||||||
"""
|
"""
|
||||||
按“已锁定R”计算目标止损位:
|
按“已锁定R”计算目标止损位:
|
||||||
@@ -4352,7 +4344,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None):
|
|||||||
closed_at_ms=close_ms,
|
closed_at_ms=close_ms,
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
guessed,
|
normalize_result_with_pnl(guessed, pnl2),
|
||||||
pnl2,
|
pnl2,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
||||||
@@ -4367,7 +4359,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None):
|
|||||||
result = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_px)
|
result = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_px)
|
||||||
if result:
|
if result:
|
||||||
return (
|
return (
|
||||||
result,
|
normalize_result_with_pnl(result, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"按交易所成交/流水同步为止盈/止损平仓",
|
"按交易所成交/流水同步为止盈/止损平仓",
|
||||||
@@ -6288,7 +6280,7 @@ def check_order_monitors():
|
|||||||
hold_seconds = calc_hold_seconds(opened_at, now)
|
hold_seconds = calc_hold_seconds(opened_at, now)
|
||||||
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
if res == "止损" and float(pnl_amount or 0) > 0:
|
if res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(res, pnl_amount)
|
res = normalize_result_with_pnl(res, pnl_amount)
|
||||||
close_order_id = ""
|
close_order_id = ""
|
||||||
@@ -6320,7 +6312,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
@@ -6351,7 +6343,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
|
|||||||
+10
-18
@@ -193,6 +193,7 @@ from history_window_lib import (
|
|||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
utc_window_to_utc_sql_strings,
|
utc_window_to_utc_sql_strings,
|
||||||
)
|
)
|
||||||
|
from trade_result_lib import normalize_result_with_pnl
|
||||||
|
|
||||||
|
|
||||||
def load_env_file(path):
|
def load_env_file(path):
|
||||||
@@ -2089,6 +2090,10 @@ def to_effective_trade_dict(row):
|
|||||||
item["display_pnl_source"] = "reviewed"
|
item["display_pnl_source"] = "reviewed"
|
||||||
else:
|
else:
|
||||||
item["display_pnl_source"] = "local"
|
item["display_pnl_source"] = "local"
|
||||||
|
item["effective_result"] = normalize_result_with_pnl(
|
||||||
|
item.get("effective_result"),
|
||||||
|
item.get("effective_pnl_amount"),
|
||||||
|
)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
@@ -2287,19 +2292,6 @@ def calc_actual_rr(pnl_amount, risk_amount):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def normalize_result_with_pnl(result, pnl_amount):
|
|
||||||
"""
|
|
||||||
触发“止损”但实际已盈利时,归类为保本止盈,避免语义混淆。
|
|
||||||
"""
|
|
||||||
if result == "止损":
|
|
||||||
try:
|
|
||||||
if float(pnl_amount or 0) > 0:
|
|
||||||
return "保本止盈"
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
||||||
"""
|
"""
|
||||||
按“已锁定R”计算目标止损位:
|
按“已锁定R”计算目标止损位:
|
||||||
@@ -3992,7 +3984,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None, *, prefer_m
|
|||||||
if guessed:
|
if guessed:
|
||||||
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
return (
|
return (
|
||||||
guessed,
|
normalize_result_with_pnl(guessed, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
||||||
@@ -4015,7 +4007,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None, *, prefer_m
|
|||||||
)
|
)
|
||||||
if result:
|
if result:
|
||||||
return (
|
return (
|
||||||
result,
|
normalize_result_with_pnl(result, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"按交易所成交记录同步为止盈/止损平仓",
|
"按交易所成交记录同步为止盈/止损平仓",
|
||||||
@@ -6047,7 +6039,7 @@ def check_order_monitors():
|
|||||||
hold_seconds = calc_hold_seconds(opened_at, now)
|
hold_seconds = calc_hold_seconds(opened_at, now)
|
||||||
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
if res == "止损" and float(pnl_amount or 0) > 0:
|
if res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(res, pnl_amount)
|
res = normalize_result_with_pnl(res, pnl_amount)
|
||||||
close_order_id = ""
|
close_order_id = ""
|
||||||
@@ -6078,7 +6070,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
@@ -6109,7 +6101,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ from history_window_lib import (
|
|||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
utc_window_to_utc_sql_strings,
|
utc_window_to_utc_sql_strings,
|
||||||
)
|
)
|
||||||
|
from trade_result_lib import normalize_result_with_pnl
|
||||||
|
|
||||||
|
|
||||||
def load_env_file(path):
|
def load_env_file(path):
|
||||||
@@ -2089,6 +2090,10 @@ def to_effective_trade_dict(row):
|
|||||||
item["display_pnl_source"] = "reviewed"
|
item["display_pnl_source"] = "reviewed"
|
||||||
else:
|
else:
|
||||||
item["display_pnl_source"] = "local"
|
item["display_pnl_source"] = "local"
|
||||||
|
item["effective_result"] = normalize_result_with_pnl(
|
||||||
|
item.get("effective_result"),
|
||||||
|
item.get("effective_pnl_amount"),
|
||||||
|
)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
@@ -2287,19 +2292,6 @@ def calc_actual_rr(pnl_amount, risk_amount):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def normalize_result_with_pnl(result, pnl_amount):
|
|
||||||
"""
|
|
||||||
触发“止损”但实际已盈利时,归类为保本止盈,避免语义混淆。
|
|
||||||
"""
|
|
||||||
if result == "止损":
|
|
||||||
try:
|
|
||||||
if float(pnl_amount or 0) > 0:
|
|
||||||
return "保本止盈"
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
||||||
"""
|
"""
|
||||||
按“已锁定R”计算目标止损位:
|
按“已锁定R”计算目标止损位:
|
||||||
@@ -3992,7 +3984,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None, *, prefer_m
|
|||||||
if guessed:
|
if guessed:
|
||||||
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
return (
|
return (
|
||||||
guessed,
|
normalize_result_with_pnl(guessed, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
||||||
@@ -4015,7 +4007,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None, *, prefer_m
|
|||||||
)
|
)
|
||||||
if result:
|
if result:
|
||||||
return (
|
return (
|
||||||
result,
|
normalize_result_with_pnl(result, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"按交易所成交记录同步为止盈/止损平仓",
|
"按交易所成交记录同步为止盈/止损平仓",
|
||||||
@@ -6047,7 +6039,7 @@ def check_order_monitors():
|
|||||||
hold_seconds = calc_hold_seconds(opened_at, now)
|
hold_seconds = calc_hold_seconds(opened_at, now)
|
||||||
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
if res == "止损" and float(pnl_amount or 0) > 0:
|
if res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(res, pnl_amount)
|
res = normalize_result_with_pnl(res, pnl_amount)
|
||||||
close_order_id = ""
|
close_order_id = ""
|
||||||
@@ -6078,7 +6070,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
@@ -6109,7 +6101,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
|
|||||||
+10
-18
@@ -192,6 +192,7 @@ from history_window_lib import (
|
|||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
utc_window_to_utc_sql_strings,
|
utc_window_to_utc_sql_strings,
|
||||||
)
|
)
|
||||||
|
from trade_result_lib import normalize_result_with_pnl
|
||||||
|
|
||||||
|
|
||||||
def load_env_file(path):
|
def load_env_file(path):
|
||||||
@@ -2038,6 +2039,10 @@ def to_effective_trade_dict(row):
|
|||||||
item["display_pnl_source"] = "reviewed"
|
item["display_pnl_source"] = "reviewed"
|
||||||
else:
|
else:
|
||||||
item["display_pnl_source"] = "local"
|
item["display_pnl_source"] = "local"
|
||||||
|
item["effective_result"] = normalize_result_with_pnl(
|
||||||
|
item.get("effective_result"),
|
||||||
|
item.get("effective_pnl_amount"),
|
||||||
|
)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
@@ -2183,19 +2188,6 @@ def calc_actual_rr(pnl_amount, risk_amount):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def normalize_result_with_pnl(result, pnl_amount):
|
|
||||||
"""
|
|
||||||
触发“止损”但实际已盈利时,归类为保本止盈,避免语义混淆。
|
|
||||||
"""
|
|
||||||
if result == "止损":
|
|
||||||
try:
|
|
||||||
if float(pnl_amount or 0) > 0:
|
|
||||||
return "保本止盈"
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
def calc_breakeven_stop(direction, entry_price, risk_fraction, locked_r, offset_pct):
|
||||||
"""
|
"""
|
||||||
按“已锁定R”计算目标止损位:
|
按“已锁定R”计算目标止损位:
|
||||||
@@ -3448,7 +3440,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None):
|
|||||||
if guessed:
|
if guessed:
|
||||||
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
return (
|
return (
|
||||||
guessed,
|
normalize_result_with_pnl(guessed, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
"未能拉取成交明细,按当前市价与止盈/止损位近似归类(建议核对交易所账单)",
|
||||||
@@ -3464,7 +3456,7 @@ def resolve_synced_flat_close(row, opened_at_str, opened_at_ms=None):
|
|||||||
pnl = calc_pnl(direction, trigger_price, exit_px, margin_capital, leverage)
|
pnl = calc_pnl(direction, trigger_price, exit_px, margin_capital, leverage)
|
||||||
if result:
|
if result:
|
||||||
return (
|
return (
|
||||||
result,
|
normalize_result_with_pnl(result, pnl),
|
||||||
pnl,
|
pnl,
|
||||||
closed_at_str,
|
closed_at_str,
|
||||||
"按交易所成交记录同步为止盈/止损平仓",
|
"按交易所成交记录同步为止盈/止损平仓",
|
||||||
@@ -5796,7 +5788,7 @@ def check_order_monitors():
|
|||||||
hold_seconds = calc_hold_seconds(opened_at, now)
|
hold_seconds = calc_hold_seconds(opened_at, now)
|
||||||
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
pnl_amount = calc_pnl(direction, trigger_price, p, margin_capital, leverage)
|
||||||
if res == "止损" and float(pnl_amount or 0) > 0:
|
if res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(res, pnl_amount)
|
res = normalize_result_with_pnl(res, pnl_amount)
|
||||||
close_order_id = ""
|
close_order_id = ""
|
||||||
@@ -5827,7 +5819,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
@@ -5857,7 +5849,7 @@ def check_order_monitors():
|
|||||||
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
guessed_res = classify_exit_by_levels(direction, trigger_price, stop_loss, take_profit, exit_p)
|
||||||
if guessed_res:
|
if guessed_res:
|
||||||
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
if guessed_res == "止损" and float(pnl_amount or 0) > 0:
|
||||||
res = "移动止盈" if breakeven_armed else "保本止盈"
|
res = normalize_result_with_pnl("止损", pnl_amount)
|
||||||
else:
|
else:
|
||||||
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
res = normalize_result_with_pnl(guessed_res, pnl_amount)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -684,8 +684,21 @@ function toggleStatsCard(){
|
|||||||
btn.innerText = collapsed ? "展开" : "折叠";
|
btn.innerText = collapsed ? "展开" : "折叠";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bindListWindowDateAutoCustom(){
|
||||||
|
const preset = document.getElementById("win-preset-select");
|
||||||
|
const fromEl = document.getElementById("win-from-utc");
|
||||||
|
const toEl = document.getElementById("win-to-utc");
|
||||||
|
function toCustom(){
|
||||||
|
if(preset) preset.value = "custom";
|
||||||
|
toggleListWindowCustom();
|
||||||
|
}
|
||||||
|
if(fromEl) fromEl.addEventListener("change", toCustom);
|
||||||
|
if(toEl) toEl.addEventListener("change", toCustom);
|
||||||
|
}
|
||||||
|
|
||||||
attachListWindowToExports();
|
attachListWindowToExports();
|
||||||
toggleListWindowCustom();
|
toggleListWindowCustom();
|
||||||
|
bindListWindowDateAutoCustom();
|
||||||
initStatsSegmentFromUrl();
|
initStatsSegmentFromUrl();
|
||||||
if(document.getElementById("journal-list")) loadJournals();
|
if(document.getElementById("journal-list")) loadJournals();
|
||||||
if(document.getElementById("review-list")) loadReviews();
|
if(document.getElementById("review-list")) loadReviews();
|
||||||
|
|||||||
@@ -115,6 +115,6 @@
|
|||||||
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
<script src="/static/manual_order_rr_preview.js?v=3"></script>
|
||||||
<script src="/static/key_monitor_form.js?v=1"></script>
|
<script src="/static/key_monitor_form.js?v=1"></script>
|
||||||
{% include 'embed_boot_scripts.html' %}
|
{% include 'embed_boot_scripts.html' %}
|
||||||
<script src="/static/instance_embed.js?v=2"></script>
|
<script src="/static/instance_embed.js?v=3"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -127,7 +127,12 @@
|
|||||||
function patchApplyListWindow() {
|
function patchApplyListWindow() {
|
||||||
if (typeof global.applyListWindow !== "function") return;
|
if (typeof global.applyListWindow !== "function") return;
|
||||||
global.applyListWindow = function embedApplyListWindow() {
|
global.applyListWindow = function embedApplyListWindow() {
|
||||||
void loadTab(getTab(), { replace: true });
|
const qs = listWindowQueryString();
|
||||||
|
const tab = getTab();
|
||||||
|
const q = new URLSearchParams(qs);
|
||||||
|
q.set("tab", tab);
|
||||||
|
q.set("embed", "1");
|
||||||
|
window.location.href = "/embed?" + q.toString();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
from trade_result_lib import normalize_result_with_pnl
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_loss_with_profit_becomes_trailing_tp():
|
||||||
|
assert normalize_result_with_pnl("止损", 4.33) == "移动止盈"
|
||||||
|
|
||||||
|
|
||||||
|
def test_manual_close_unchanged_even_with_profit():
|
||||||
|
assert normalize_result_with_pnl("手动平仓", 10) == "手动平仓"
|
||||||
|
|
||||||
|
|
||||||
|
def test_stop_loss_with_loss_unchanged():
|
||||||
|
assert normalize_result_with_pnl("止损", -2.5) == "止损"
|
||||||
|
|
||||||
|
|
||||||
|
def test_take_profit_unchanged():
|
||||||
|
assert normalize_result_with_pnl("止盈", 5) == "止盈"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
"""交易结果展示与入库时的语义归一化。"""
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_result_with_pnl(result, pnl_amount):
|
||||||
|
"""
|
||||||
|
非手动平仓且实际盈利时,不应记为「止损」。
|
||||||
|
程序触发的止损类平仓若盈亏为正,归类为「移动止盈」。
|
||||||
|
"""
|
||||||
|
res = (result or "").strip()
|
||||||
|
if res == "手动平仓":
|
||||||
|
return res
|
||||||
|
if res == "止损":
|
||||||
|
try:
|
||||||
|
if float(pnl_amount or 0) > 0:
|
||||||
|
return "移动止盈"
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
return res
|
||||||
Reference in New Issue
Block a user