Add daily loss-count freeze for account risk cooldown.
RISK_DAILY_LOSS_LIMIT (default 2, 0 disables) freezes new opens after N losing closes in the trading day. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,6 +20,7 @@ from lib.trade.account_risk_lib import (
|
||||
enrich_risk_status_countdown,
|
||||
ensure_account_risk_schema,
|
||||
max_active_positions_from_env,
|
||||
on_closed_trade_pnl,
|
||||
on_journal_saved,
|
||||
on_manual_close,
|
||||
on_user_initiated_close,
|
||||
@@ -58,6 +59,7 @@ class AccountRiskLibTests(unittest.TestCase):
|
||||
os.environ["RISK_COOLING_HOURS_MANUAL"] = "4"
|
||||
os.environ["RISK_COOLING_HOURS_MANUAL_JOURNAL"] = "1"
|
||||
os.environ["RISK_MANUAL_CLOSE_DAILY_LIMIT"] = "2"
|
||||
os.environ["RISK_DAILY_LOSS_LIMIT"] = "2"
|
||||
os.environ["RISK_MOOD_ISSUES_DAILY_FREEZE"] = "1"
|
||||
os.environ["APP_TIMEZONE"] = "Asia/Shanghai"
|
||||
|
||||
@@ -521,6 +523,41 @@ class AccountRiskLibTests(unittest.TestCase):
|
||||
os.environ["MAX_ACTIVE_POSITIONS"] = "3"
|
||||
self.assertEqual(max_active_positions_from_env(), 3)
|
||||
|
||||
def test_daily_loss_limit_freezes_on_second_loss(self):
|
||||
conn = _mem_conn()
|
||||
now = datetime(2026, 6, 14, 12, 0, 0)
|
||||
on_closed_trade_pnl(conn, pnl_amount=-1.5, trading_day="2026-06-14", now=now)
|
||||
st = compute_account_risk_status(conn, trading_day="2026-06-14", now=now)
|
||||
self.assertEqual(st["daily_loss_count"], 1)
|
||||
self.assertEqual(st["status"], STATUS_NORMAL)
|
||||
on_closed_trade_pnl(conn, pnl_amount=-0.2, trading_day="2026-06-14", now=now)
|
||||
st2 = compute_account_risk_status(conn, trading_day="2026-06-14", now=now)
|
||||
self.assertEqual(st2["daily_loss_count"], 2)
|
||||
self.assertEqual(st2["status"], STATUS_DAILY)
|
||||
self.assertFalse(st2["can_trade"])
|
||||
self.assertIn("日亏损", st2["reason"])
|
||||
|
||||
def test_daily_loss_limit_zero_disables(self):
|
||||
os.environ["RISK_DAILY_LOSS_LIMIT"] = "0"
|
||||
conn = _mem_conn()
|
||||
now = datetime(2026, 6, 14, 12, 0, 0)
|
||||
on_closed_trade_pnl(conn, pnl_amount=-10, trading_day="2026-06-14", now=now)
|
||||
on_closed_trade_pnl(conn, pnl_amount=-10, trading_day="2026-06-14", now=now)
|
||||
st = compute_account_risk_status(conn, trading_day="2026-06-14", now=now)
|
||||
self.assertEqual(st["daily_loss_count"], 0)
|
||||
self.assertEqual(st["daily_loss_limit"], 0)
|
||||
self.assertEqual(st["status"], STATUS_NORMAL)
|
||||
self.assertTrue(st["can_trade"])
|
||||
|
||||
def test_profitable_close_does_not_count_loss(self):
|
||||
conn = _mem_conn()
|
||||
now = datetime(2026, 6, 14, 12, 0, 0)
|
||||
on_closed_trade_pnl(conn, pnl_amount=3.2, trading_day="2026-06-14", now=now)
|
||||
on_closed_trade_pnl(conn, pnl_amount=0, trading_day="2026-06-14", now=now)
|
||||
st = compute_account_risk_status(conn, trading_day="2026-06-14", now=now)
|
||||
self.assertEqual(st["daily_loss_count"], 0)
|
||||
self.assertEqual(st["status"], STATUS_NORMAL)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user