Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Line-ending policy.
#
# Shell scripts must keep LF in the working tree: a CRLF checkout makes
# `bash scripts/*.sh` fail with `$'\r': command not found`, and a Windows
# working copy is also what a local Docker build would copy into the
# containers, so the breakage is not limited to the developer's own shell.
#
# `text eol=lf` overrides core.autocrlf for the matched paths, so the outcome
# no longer depends on each contributor's local Git configuration
# (github.com docs, "Configuring Git to handle line endings": a committed
# .gitattributes "overrides the core.autocrlf setting for all repository
# contributors"; gitattributes(5): the eol attribute "sets a specific
# line-ending style to be used in the working directory").
*.sh text eol=lf
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,4 @@ snapshot、HypothesisSpec 确定性编译、五代 8×3 共演化、单冠军 Fo

---

> 本文件是协议入口,**短小**为美。详细规则在公开的 `docs/00-03` 与 `docs/brand/`。
> 本文件是协议入口,**短小**为美。详细规则在公开的 `docs/00-05`。
316 changes: 316 additions & 0 deletions agent_onboarding.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/dashboard/src/i18n/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineRouting } from "next-intl/routing";

/**
* 与官网 apps/web 保持一致:en 默认无前缀,zh 走 /zh。
* 控制台是动态应用,locale 协商靠 middleware(见 src/middleware.ts)。
* 控制台是动态应用,locale 协商靠 middleware(见 src/proxy.ts)。
*/
export const routing = defineRouting({
locales: ["en", "zh"],
Expand Down
6 changes: 3 additions & 3 deletions docs/01-architecture-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
┌───────────────────────────────▼──────────────────────────────────────┐
│ 编排层 · packages/orchestration · Mastra (TypeScript) │
│ │
│ agents/ orchestrator → trader / risk(按市场分类自动路由 venue)│
│ agents/ 单个 orchestrator agent(按市场分类自动路由 venue) │
│ tools/ data.* web.* factor.* research.* paper.* trade.* evolver.*│
│ swarm.* │
│ + mcp__<server>__<verb>(可插拔外部 MCP) │
│ hooks/ 5 类生命周期事件 + Stop(PreToolUse / PostToolUse / …) │
│ hooks/ 6 类生命周期事件(PreToolUse / PostToolUse / Stop …) │
│ permissions/ allow / ask / deny 三态(deny > allow > ask > default) │
│ plan/exec create_plan → approve_plan → execute_plan(一次性 token)│
│ memory/ PostgresStore · 用户偏好 / 历史会话;plan 由 paper DB 持久化│
│ memory/ LibSQL 存储(.data/)· 会话与偏好;plan 由 paper DB 持久化 │
└───────────────────────────────┬──────────────────────────────────────┘
│ HTTP / MCP(每个 tool 调对应服务)
┌──────────┬──────────┬──────────┬──────────┬──────────┐
Expand Down
3 changes: 2 additions & 1 deletion packages/orchestration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Mastra / TypeScript 编排层:把 Python services 和外部 MCP 包装成 agen

## 当前职责

- **Agent 路由**:orchestrator 协调 trader、risk、research-hub,并按市场分类选择数据源。
- **Agent 路由**:单个 orchestrator agent 直接调用各 tool,并按市场分类选择数据源
(trader / risk 子 agent 已在 D-8a′ 移除;下单仍走 plan/exec,模型没有直下单 tool)。
- **Tool 族**:`data.*` / `web.*` / `factor.*` / `research.*` / `paper.*` / `trade.*` /
`evolver.*` / `swarm.*` / `skill.*` / `risk.*` / `scheduler.*` / `divination.*` /
`sandbox.*`,以及可插拔 `mcp__<server>__<verb>`。
Expand Down
14 changes: 7 additions & 7 deletions packages/orchestration/src/mastra/memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
* 如果 caller 漏传 ``resourceId``,Mastra 默认会用空字符串 → **不同用户共享同一空
* 桶** → 历史互窜 + 隐私泄漏。
*
* 上 prod 前必须:
* 约束:
*
* 1. 在 agent.generate / stream 入口(apps/web Next.js API route)强制
* ``assertScopedRequest({ resourceId, threadId })``
* 2. ``resourceId`` 从 session.user.id 派生,**不能**让客户端任意传
* 3. LibSQLStore 换成 PostgresStore 走与业务表同一 PG(按 user_id 分区)
*
* 改成多实例 / 隔离的触发条件:上多用户 / live trading 时按 ADR-0011 §isolation 拆。
* 1. 调用方(dashboard BFF → mastra agent 入口)必须传 ``resourceId`` / ``threadId``,
* 并自行调用 ``assertScopedRequest``——它不会自动生效
* 2. ``resourceId`` 必须来自已认证会话(identity middleware 写入的 sub),**不能**让
* 客户端任意传
* 3. LibSQL 是单写者文件库:单实例部署够用;要改成多实例 / 按 owner 隔离时再换
* PostgresStore,走与业务表同一 PG
*/
import { LibSQLStore } from "@mastra/libsql";
import { Memory } from "@mastra/memory";
Expand Down
159 changes: 0 additions & 159 deletions services/data/src/inalpha_data/cache_manager.py

This file was deleted.

9 changes: 7 additions & 2 deletions services/evolver/src/inalpha_evolver/evaluator/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,17 @@ async def evaluate(
initial_cash: float = 10000.0,
fee_rate: float = 0.001,
) -> EvaluationResult:
"""评估单个候选策略(E1 需要 data service 运行)。"""
"""在内存里评估单个候选策略。

注意:本类尚未接 data service,``bars`` 传空列表,因此**没有真实行情**。
E1 生产路径走 ``FrozenDatasetEvaluator``(冻结 bars + manifest 校验),
不要用本类做真实评估。
"""
symbol = universe[0] if universe else "BTCUSDT"

fn = partial(
run_engine_in_subprocess,
bars=[], # TODO: 从 data service 拉 bars
bars=[], # 未接 data service;生产路径见 FrozenDatasetEvaluator
instrument_id=symbol,
timeframe=timeframe,
strategy_id=None,
Expand Down
5 changes: 3 additions & 2 deletions services/paper/src/inalpha_paper/api/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
async def health() -> HealthResponse:
"""liveness。

paper service D-6 不直接连 DB(只调 data-service),所以不做 DB ping。
D-7 持久化 backtest_runs 之后会加 DB ping。
paper 的业务数据(accounts / orders / positions / runs / plans / wallets)都在
PostgreSQL,但本端点**刻意只做进程探活**:不连 DB、不反映依赖健康,DB 不可用时
仍会返回 200。需要依赖健康时另做 readiness 检查。
"""
return HealthResponse(status="ok", service="paper", version=__version__)
6 changes: 4 additions & 2 deletions services/paper/src/inalpha_paper/engine/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""引擎:Portfolio + BacktestEngine + Report。

D-5 范围:``BacktestEngine`` 把 D-3 data + D-4 kernel + D-5 execution 串起来跑完整闭环。
D-6 起:``LiveEngine``(asyncio 事件循环 + LiveGateway)。
``BacktestEngine`` 把 data + kernel + execution 串起来跑完整回测闭环。
模拟盘不走独立的 LiveEngine:``LiveRunnerManager`` 用 ``engine/live_session.py`` 把
已收盘 bar 喂给同一个内核(``TestClock`` 驱动),live runner 的调度、审批与落库在
``live_runner.py``。
"""
from .backtest import BacktestEngine
from .portfolio import Portfolio
Expand Down
13 changes: 6 additions & 7 deletions services/paper/src/inalpha_paper/execution/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
"""执行链:Strategy → RiskEngine → ExecutionEngine → Gateway → Exchange / 真实经纪商。

D-5 范围:
当前内容:

- ``Gateway`` 抽象 + ``SimulatedExchange``(一并实现 venue 撮合,回测专用)
- ``RiskEngine`` —— D-5 简化版 pass-through,规则化校验在 ADR-0011 落地(Mastra 编排层)
- ``Gateway`` 抽象 + ``SimulatedExchange``(一并实现 venue 撮合)
- ``RiskEngine`` —— 内核内风控守门(Order 进 Execution 前必经)
- ``ExecutionEngine`` —— Order 状态机管理 + 路由
- 规则化风控已落地在 ``risk_rules/``:回测路径由 ``RiskEngine`` 执行、HTTP 路径由
``RiskGuard`` 执行并落 ``risk_locks``;运行状态见 ``docs/04-current-state.md``

D-6+ 范围:

- ``LiveGateway`` 接 Binance via CCXT
- Risk 规则化校验(hook + permission 体系)
没有 ``LiveGateway``:不接真实经纪商,模拟盘成交走 ``SimulatedExchange`` + DB 侧 executor。
"""
from .exchange import EXECUTION_ENGINE_ENDPOINT, SimulatedExchange
from .execution_engine import ExecutionEngine
Expand Down
8 changes: 4 additions & 4 deletions services/paper/src/inalpha_paper/execution/gateway.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""Gateway 抽象 —— 经纪商 / 交易所接入。

设计依据 [refs/vnpy.md §3 §7](../../../../docs/refs/vnpy.md),把 vnpy 的 7 个抽象方法
裁剪到 MVP 需要的:
设计依据 vnpy 的 Gateway 抽象(§3 §7),把它的 7 个抽象方法裁剪到当前需要的:

- ``send_order`` —— 唯一必须实现
- ``cancel_order`` / ``modify_order`` —— 可选(不实现就 raise NotImplementedError)

D-5 起只有 ``SimulatedExchange`` 一个实现(同时承担 venue 撮合职责)。D-6 起加
``LiveGateway``(CCXT Binance)。
当前只有 ``SimulatedExchange`` 一个实现(同时承担 venue 撮合职责)。没有连接真实经纪商
的 gateway:模拟盘成交由 ``SimulatedExchange`` + DB 侧 ``OrderExecutor`` 完成,回测与
模拟盘共用同一份策略代码,只换 Clock。
"""
from __future__ import annotations

Expand Down
5 changes: 3 additions & 2 deletions services/paper/src/inalpha_paper/kernel/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,12 @@ def now_ns(self) -> int:

def set_timer(self, name: str, interval_ns: int, callback: TimerCallback) -> None:
raise NotImplementedError(
"LiveClock.set_timer requires asyncio loop, attached in Engine (D-5)"
"LiveClock.set_timer is not implemented; the live path drives TestClock "
"from closed bars instead (see engine/live_session.py)"
)

def cancel_timer(self, name: str) -> None:
# D-5 起会实现,目前 noop(保持接口对称)
# 未实现定时器,保持接口对称;实时路径不经 timer
pass


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

fitness = sharpe
+ 0.3 * calmar
- 0.10 * turnover_penalty # turnover / 252(年化换手)
- 0.10 * turnover_penalty # 每根 bar 平均交易数 × 100
- 1.0 * (drawdown > 0.30) # 30% 回撤一票否决

MVP 留空:``capacity_penalty``(需 ADV 数据,D-10+ 引入)。
Expand Down