Show recent filled plans in the demo analysis prompt
List each plan filled in the last 24 hours with its zone, entry, fill and close times, close reason and net result, so the model can apply the skill rules on consecutive stops, re-entry after a stop and the daily entry cap.
This commit is contained in:
1 parent
23a9a5175e
commit
fcaedfb358
1 file changed
+22
-1
@@ -7,7 +7,7 @@ import asyncio
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime, timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
@@ -21,6 +21,7 @@ from alphapulse.core.db import SessionLocal
|
|||||||
from alphapulse.models import AiProvider, TradingAccount, TradingAnalysis, TradingEvent, TradingOrder, TradingSymbol
|
from alphapulse.models import AiProvider, TradingAccount, TradingAnalysis, TradingEvent, TradingOrder, TradingSymbol
|
||||||
from alphapulse.trading import plan as rules
|
from alphapulse.trading import plan as rules
|
||||||
from alphapulse.trading.client import ExchangeError, mark_price, symbol_rules
|
from alphapulse.trading.client import ExchangeError, mark_price, symbol_rules
|
||||||
|
from alphapulse.trading.executor import CLOSE_REASON_LABELS
|
||||||
from alphapulse.trading.plan import PlanContext, PlanError, TradePlan, atr, check_setup, parse_bars
|
from alphapulse.trading.plan import PlanContext, PlanError, TradePlan, atr, check_setup, parse_bars
|
||||||
from alphapulse.trading.snapshot import read_snapshot
|
from alphapulse.trading.snapshot import read_snapshot
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@ READ_TOOLS = ("search_news", "get_news", "search_symbols", "get_klines", "get_ti
|
|||||||
# 最后一轮只开放 submit_trade_plan,逼模型给出结论
|
# 最后一轮只开放 submit_trade_plan,逼模型给出结论
|
||||||
MAX_ROUNDS = 6
|
MAX_ROUNDS = 6
|
||||||
RECENT_DECISIONS = 2
|
RECENT_DECISIONS = 2
|
||||||
|
# skill 的连续止损暂停、止损后冷却、每日开仓上限要靠这段成交记录判断
|
||||||
|
RECENT_TRADES_HOURS = 24
|
||||||
DIRECTION_LABELS = {"long": "做多", "short": "做空"}
|
DIRECTION_LABELS = {"long": "做多", "short": "做空"}
|
||||||
CONFIDENCE_LABELS = {"high": "高", "medium": "中", "low": "低"}
|
CONFIDENCE_LABELS = {"high": "高", "medium": "中", "low": "低"}
|
||||||
ACTION_LABELS = {"plan": "新计划", "keep": "维持当前计划", "exit": "结束当前计划", "wait": "观望"}
|
ACTION_LABELS = {"plan": "新计划", "keep": "维持当前计划", "exit": "结束当前计划", "wait": "观望"}
|
||||||
@@ -107,6 +110,15 @@ def plan_brief(decision: dict, sizing: dict | None) -> dict:
|
|||||||
return brief
|
return brief
|
||||||
|
|
||||||
|
|
||||||
|
def trade_brief(a: TradingAnalysis) -> str:
|
||||||
|
setup = a.decision["setup"]
|
||||||
|
head = (f"#{a.id} {DIRECTION_LABELS[a.decision['direction']]},区间 {setup['zone_low']}–{setup['zone_high']},"
|
||||||
|
f"挂单 {a.sizing['entry']['price']},{local(a.first_fill_at)} 成交")
|
||||||
|
if a.plan_status != "closed":
|
||||||
|
return f"{head},{'持仓中' if a.plan_status == 'open' else '平仓中'}"
|
||||||
|
return f"{head},{local(a.closed_at)} {CLOSE_REASON_LABELS.get(a.close_reason, a.close_reason)},净 {Decimal(a.result['net']):.2f} USDT"
|
||||||
|
|
||||||
|
|
||||||
async def recent_atr(symbol: str) -> Decimal:
|
async def recent_atr(symbol: str) -> Decimal:
|
||||||
"""最近已收盘 5m K 线的 ATR14,用于计算止损"""
|
"""最近已收盘 5m K 线的 ATR14,用于计算止损"""
|
||||||
bars = parse_bars(await market_client.get("um", "klines", {"symbol": symbol, "interval": rules.ATR_INTERVAL, "limit": rules.ATR_PERIOD + 2}))
|
bars = parse_bars(await market_client.get("um", "klines", {"symbol": symbol, "interval": rules.ATR_INTERVAL, "limit": rules.ATR_PERIOD + 2}))
|
||||||
@@ -152,6 +164,12 @@ async def prepare(symbol: str, reasons: list[str], analysis_id: int) -> Prepared
|
|||||||
.where(TradingAnalysis.symbol == symbol, TradingAnalysis.status == "done", TradingAnalysis.id != analysis_id)
|
.where(TradingAnalysis.symbol == symbol, TradingAnalysis.status == "done", TradingAnalysis.id != analysis_id)
|
||||||
.order_by(TradingAnalysis.id.desc()).limit(RECENT_DECISIONS)
|
.order_by(TradingAnalysis.id.desc()).limit(RECENT_DECISIONS)
|
||||||
)).all()
|
)).all()
|
||||||
|
trades = (await session.scalars(
|
||||||
|
select(TradingAnalysis)
|
||||||
|
.where(TradingAnalysis.symbol == symbol, TradingAnalysis.dry_run.is_(False),
|
||||||
|
TradingAnalysis.first_fill_at >= datetime.now(UTC) - timedelta(hours=RECENT_TRADES_HOURS))
|
||||||
|
.order_by(TradingAnalysis.first_fill_at.desc())
|
||||||
|
)).all()
|
||||||
current = await session.scalar(
|
current = await session.scalar(
|
||||||
select(TradingAnalysis)
|
select(TradingAnalysis)
|
||||||
.where(TradingAnalysis.symbol == symbol, TradingAnalysis.plan_status.in_(("pending", "open", "closing")), TradingAnalysis.dry_run.is_(False))
|
.where(TradingAnalysis.symbol == symbol, TradingAnalysis.plan_status.in_(("pending", "open", "closing")), TradingAnalysis.dry_run.is_(False))
|
||||||
@@ -214,6 +232,9 @@ async def prepare(symbol: str, reasons: list[str], analysis_id: int) -> Prepared
|
|||||||
"## 最近决策(新的在前)",
|
"## 最近决策(新的在前)",
|
||||||
*([f"- {local(a.started_at)}{'(试运行)' if a.dry_run else ''}:{dump(plan_brief(a.decision, a.sizing))}" for a in recent] or ["无"]),
|
*([f"- {local(a.started_at)}{'(试运行)' if a.dry_run else ''}:{dump(plan_brief(a.decision, a.sizing))}" for a in recent] or ["无"]),
|
||||||
"",
|
"",
|
||||||
|
f"## 近 {RECENT_TRADES_HOURS} 小时已成交的计划(新的在前,共 {len(trades)} 次开仓)",
|
||||||
|
*([f"- {trade_brief(a)}" for a in trades] or ["无"]),
|
||||||
|
"",
|
||||||
"## 预取的行情(实盘数据,已取,不要用相同参数重复调用)",
|
"## 预取的行情(实盘数据,已取,不要用相同参数重复调用)",
|
||||||
await prefetch(symbol),
|
await prefetch(symbol),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in new issue
Block a user