fix(trend): correct DCA triggers and partial-position PnL across exchanges
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+36
-27
@@ -24,6 +24,8 @@ from strategy_trend_lib import (
|
||||
build_grid_prices,
|
||||
build_leg_amounts_json,
|
||||
calc_risk_fraction,
|
||||
trend_dca_level_reached,
|
||||
trend_effective_margin_capital,
|
||||
validate_trend_bounds,
|
||||
)
|
||||
from strategy_trade_labels import (
|
||||
@@ -548,14 +550,22 @@ def _finalize_plan(cfg: dict, conn, row, result_label: str, exit_price: float) -
|
||||
closed_at = m.app_now_str()
|
||||
opened_at = row["opened_at"] or closed_at
|
||||
hold_seconds = m.calc_hold_seconds(opened_at, m.parse_dt_for_trading_day(closed_at) or m.app_now())
|
||||
margin_cap = float(row["plan_margin_capital"] or 0)
|
||||
plan_margin = float(row["plan_margin_capital"] or 0)
|
||||
margin_cap = trend_effective_margin_capital(_row(cfg, row))
|
||||
lev = int(row["leverage"] or 1)
|
||||
avg_e = float(row["avg_entry_price"] or 0)
|
||||
pnl_amount = m.calc_pnl(direction, avg_e, float(exit_price), margin_cap, lev)
|
||||
res = m.normalize_result_with_pnl(result_label, pnl_amount)
|
||||
risk_amt = m.calc_risk_amount_from_plan(
|
||||
direction, float(row["add_upper"]), float(row["stop_loss"]), margin_cap, lev
|
||||
direction, float(row["add_upper"]), float(row["stop_loss"]), plan_margin, lev
|
||||
)
|
||||
try:
|
||||
target = float(row["target_order_amount"] or 0)
|
||||
open_amt = float(row["order_amount_open"] or 0)
|
||||
if risk_amt is not None and target > 0 and open_amt > 0:
|
||||
risk_amt = round(float(risk_amt) * min(1.0, open_amt / target), 6)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
planned_rr = m.calc_rr_ratio(direction, avg_e, float(row["stop_loss"]), float(row["take_profit"]))
|
||||
try:
|
||||
cancel_symbol_orders(cfg, ex_sym)
|
||||
@@ -785,32 +795,31 @@ def check_trend_pullback_plans(cfg: dict) -> None:
|
||||
_TREND_FLAT_STREAK.pop(plan_id, None)
|
||||
continue
|
||||
if int(row["first_order_done"] or 0) and legs_done < len(grid) and legs_done < len(leg_amounts):
|
||||
level = float(grid[legs_done])
|
||||
fired = False
|
||||
if direction == "long":
|
||||
fired = last_pf > level and pf <= level
|
||||
else:
|
||||
fired = last_pf < level and pf >= level
|
||||
if fired:
|
||||
while legs_done < len(grid) and legs_done < len(leg_amounts):
|
||||
level = float(grid[legs_done])
|
||||
if not trend_dca_level_reached(direction, pf, level):
|
||||
break
|
||||
amt = float(m.exchange.amount_to_precision(ex_sym, leg_amounts[legs_done]))
|
||||
if amt > 0:
|
||||
add_resp = trend_market_add(cfg, ex_sym, direction, amt, lev)
|
||||
fill_px = m.extract_trade_price_from_order(add_resp) or pf
|
||||
old_avg = float(row["avg_entry_price"] or fill_px)
|
||||
old_open = float(row["order_amount_open"] or 0)
|
||||
new_avg = _weighted_avg(old_avg, old_open, fill_px, amt)
|
||||
conn.execute(
|
||||
"UPDATE trend_pullback_plans SET legs_done=?, avg_entry_price=?, "
|
||||
"order_amount_open=?, last_mark_price=? WHERE id=?",
|
||||
(legs_done + 1, new_avg, old_open + amt, pf, row["id"]),
|
||||
)
|
||||
row = conn.execute(
|
||||
"SELECT * FROM trend_pullback_plans WHERE id=?", (row["id"],)
|
||||
).fetchone()
|
||||
try:
|
||||
trend_refresh_stop_only(cfg, ex_sym, direction, sl)
|
||||
except Exception:
|
||||
pass
|
||||
if amt <= 0:
|
||||
break
|
||||
add_resp = trend_market_add(cfg, ex_sym, direction, amt, lev)
|
||||
fill_px = m.extract_trade_price_from_order(add_resp) or pf
|
||||
old_avg = float(row["avg_entry_price"] or fill_px)
|
||||
old_open = float(row["order_amount_open"] or 0)
|
||||
new_avg = _weighted_avg(old_avg, old_open, fill_px, amt)
|
||||
legs_done += 1
|
||||
conn.execute(
|
||||
"UPDATE trend_pullback_plans SET legs_done=?, avg_entry_price=?, "
|
||||
"order_amount_open=?, last_mark_price=? WHERE id=?",
|
||||
(legs_done, new_avg, old_open + amt, pf, row["id"]),
|
||||
)
|
||||
row = conn.execute(
|
||||
"SELECT * FROM trend_pullback_plans WHERE id=?", (row["id"],)
|
||||
).fetchone()
|
||||
try:
|
||||
trend_refresh_stop_only(cfg, ex_sym, direction, sl)
|
||||
except Exception:
|
||||
pass
|
||||
conn.execute(
|
||||
"UPDATE trend_pullback_plans SET last_mark_price=? WHERE id=?",
|
||||
(pf, row["id"]),
|
||||
|
||||
Reference in New Issue
Block a user