接入 SimNow 模拟盘与期货下单、策略及品种推荐功能。

新增 vnpy CTP 桥接、以损定仓/固定张数、趋势回调与滚仓策略、按资金推荐品种及交易风控;模拟盘走 SimNow,实盘预留期货公司配置。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-24 10:04:37 +08:00
parent 9c0e5d9c57
commit 6e423eebfb
30 changed files with 2789 additions and 60 deletions
+56 -3
View File
@@ -34,6 +34,9 @@ from kline_store import ensure_kline_tables
from kline_stream import kline_hub, sse_format
from kline_chart import generate_review_kline_chart, fetch_market_klines, MARKET_PERIODS
from market import get_price as market_get_price, set_ths_refresh_token, get_quote_source_label
from strategy.strategy_db import init_strategy_tables
from install_trading import install_trading
from vnpy_bridge import try_init_vnpy
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
@@ -306,6 +309,7 @@ def init_db():
data_json TEXT NOT NULL,
updated_at TEXT NOT NULL)''')
ensure_kline_tables(conn)
init_strategy_tables(conn)
conn.commit()
conn.close()
@@ -322,6 +326,12 @@ def init_db():
if not get_setting("fee_multiplier"):
set_setting("fee_multiplier", "2")
if not get_setting("trading_mode"):
set_setting("trading_mode", "simulation")
if not get_setting("position_sizing_mode"):
set_setting("position_sizing_mode", "risk")
if not get_setting("risk_percent"):
set_setting("risk_percent", "1")
conn = get_db()
fee_cnt = conn.execute("SELECT COUNT(*) FROM fee_rates").fetchone()[0]
conn.close()
@@ -569,6 +579,9 @@ def background_task():
expire_old_plans()
check_key_monitors()
check_order_plans()
fn = getattr(app, "_check_trend_plans", None)
if fn:
fn(app)
except Exception:
pass
time.sleep(3)
@@ -583,8 +596,6 @@ def start_background_threads():
threading.Thread(target=refresh_main_index, daemon=True).start()
start_background_threads()
# —————————————— 登录 ——————————————
def login_required(f):
@@ -1278,6 +1289,14 @@ def add_review():
d.get("notes", "").strip(),
),
)
hook = getattr(app, "_risk_review_hook", None)
if hook:
hook(
conn,
",".join(tags),
exit_trigger,
d.get("exit_supplement", "").strip(),
)
conn.commit()
conn.close()
touch_stats_cache()
@@ -1535,9 +1554,25 @@ def settings():
flash("实盘资金不能为负数")
else:
set_setting("live_capital", str(val))
flash("实盘资金已保存")
flash("参考资金已保存CTP 已连接时以 SimNow/柜台权益为准)")
except ValueError:
flash("请输入有效的实盘资金金额")
elif action == "trading":
mode = request.form.get("trading_mode", "simulation").strip()
if mode not in ("simulation", "live"):
mode = "simulation"
sizing = request.form.get("position_sizing_mode", "risk").strip()
if sizing not in ("fixed", "risk"):
sizing = "risk"
set_setting("trading_mode", mode)
set_setting("position_sizing_mode", sizing)
try:
rp = float(request.form.get("risk_percent", "1") or 1)
set_setting("risk_percent", str(max(0.1, min(100.0, rp))))
except ValueError:
flash("风险比例无效")
return redirect(url_for("settings"))
flash("交易模式已保存")
elif action == "password":
old_p = request.form.get("old_password", "")
new_p = request.form.get("new_password", "")
@@ -1563,8 +1598,26 @@ def settings():
username=username,
live_capital=live_capital,
quote_label=get_quote_source_label(),
trading_mode=get_setting("trading_mode", "simulation"),
position_sizing_mode=get_setting("position_sizing_mode", "risk"),
risk_percent=get_setting("risk_percent", "1"),
)
install_trading(
app,
login_required=login_required,
get_db=get_db,
get_setting=get_setting,
set_setting=set_setting,
fetch_price=fetch_price,
send_wechat_msg=send_wechat_msg,
)
try_init_vnpy({})
start_background_threads()
# —————————————— 启动 ——————————————
if __name__ == "__main__":