从零构建模块化交易智能体:Python量化交易框架实战
1. 项目概述:从零构建一个交易智能体
最近几年,量化交易的门槛似乎在不断降低,但真正能稳定盈利、逻辑自洽的策略却依然稀缺。很多朋友可能都尝试过用Python写几个简单的均线策略,回测结果看起来很美,但一上实盘就“见光死”。这背后往往不是策略逻辑本身的问题,而是整个交易执行流程的健壮性、风控的完备性以及策略与市场交互的“智能”程度不够。
今天我想和大家深入聊聊一个我最近在研究和实践的项目方向: 构建一个完整的、模块化的交易智能体(Trading Agent) 。这个项目的核心,不是提供一个“圣杯”策略,而是搭建一个可以承载、测试、迭代和自动化执行任何交易逻辑的框架。你可以把它想象成一个交易员的“数字孪生”,它需要具备感知市场(数据)、分析决策(策略)、执行交易(下单)以及复盘学习(优化)的全链路能力。
我参考并重构了
TauricResearch/TradingAgents
这个开源项目的核心思想,但更侧重于从工程实践和业务逻辑的角度,分享如何一步步搭建这样一个系统。它适合有一定Python基础,对金融市场有基本了解,并且希望将自己的交易想法系统化、自动化的朋友。无论你是想验证一个主观交易逻辑,还是想运行一个复杂的多因子模型,一个设计良好的交易智能体框架都能让你事半功倍,并且能有效隔离策略逻辑与底层API的复杂性,让你的核心精力聚焦在alpha的挖掘上。
2. 交易智能体的核心架构设计
2.1 为什么需要模块化设计?
在动手写第一行代码之前,我们必须想清楚架构。一个常见的误区是,把数据获取、信号计算、订单管理和风险控制的所有代码都揉在一个巨大的
main.py
文件里。初期可能跑得起来,但随着策略复杂度的增加,这种“意大利面条式”的代码会变得极难维护、调试和扩展。
模块化设计的核心思想是 “高内聚、低耦合” 。我们将整个交易流程分解为几个职责分明的组件,每个组件只负责一件事,并且通过清晰的接口与其他组件通信。这样做的好处显而易见:
- 可测试性 :你可以单独测试数据模块的稳定性,或者回测策略模块的历史表现,而不需要启动整个交易系统。
- 可复用性 :一个优秀的订单执行模块,可以服务于无数个不同的策略模块。
- 可维护性 :当交易所API更新时,你只需要修改底层的连接器模块,上层的策略逻辑可能完全不受影响。
- 策略迭代速度 :你可以像搭积木一样,快速组合不同的市场数据源、策略算法和执行器,进行A/B测试。
基于这些考量,我设计的核心架构通常包含以下五个层次:
- 数据层(Data Layer) :负责从各种源头(交易所WebSocket、REST API、数据库、本地CSV)实时或定期获取、清洗、存储市场数据(K线、深度、tick等)。它是整个系统的感官。
- 策略层(Strategy Layer) :这是交易逻辑的核心。它接收处理好的数据,运行你的算法(无论是简单的技术指标还是复杂的机器学习模型),并输出交易信号(例如:“在价格达到100时买入1个BTC”)。
- 风控层(Risk Layer) :在信号被执行前,必须经过风控层的审查。它检查当前仓位、资金利用率、单笔风险、最大回撤等,有权否决或修改策略层发出的信号。这是保证系统生存的“刹车系统”。
- 执行层(Execution Layer) :负责将风控层通过后的信号,转化为具体的交易所订单。它需要处理订单类型(市价/限价)、拆单、滑点控制、订单生命周期管理(撤单、改单)等复杂细节。
- 监控与日志层(Monitor & Logging Layer) :记录所有关键事件(信号产生、订单状态变化、账户余额变动)、性能指标,并提供实时监控面板(Dashboard)或报警(如Telegram消息)。这是系统的“黑匣子”和“仪表盘”。
2.2 核心组件交互流程
一个典型的交易周期(例如,每收到一根新的1分钟K线)的交互流程如下:
- 数据驱动 :数据层获取到新的市场数据,并推送给所有订阅该数据的策略实例。
- 策略计算 :策略实例根据新数据更新其内部状态,运行逻辑,判断是否产生交易信号。信号是一个结构化的对象,至少包含:交易方向(多/空)、标的、数量、建议价格、信号类型等。
- 风控审核 :策略产生的信号被发送到风控层。风控层根据全局账户状态和风控规则(如:“单品种仓位不超过总资金的20%”、“日内交易次数上限为50次”)进行审核。审核通过则传递原始或修改后的信号;审核拒绝则记录日志并丢弃信号。
- 订单执行 :执行层收到审核后的信号,根据当前市场情况(如盘口深度)和预设的执行算法(如TWAP、VWAP),生成具体的订单指令,并通过交易所API发送。
- 状态反馈 :交易所的订单状态更新(如部分成交、完全成交、被拒绝)通过执行层反馈给风控层和策略层,更新各自的内部状态(如可用资金、当前仓位)。
- 全程记录 :监控层记录以上所有步骤的详细信息,并更新性能指标。
这个流程形成了一个闭环,确保了策略决策与市场实况、账户状态的同步。
注意 :在设计初期,务必明确各模块之间的数据传递格式。我强烈建议使用Python的
dataclass或pydantic的BaseModel来定义这些数据结构(如MarketData,TradeSignal,OrderRequest)。这能在开发早期就通过类型提示避免很多低级错误,并且使代码的意图非常清晰。
3. 关键模块的深度实现与选型
3.1 数据层:稳定与效率的基石
数据是策略的粮食,数据层的稳定性和效率直接决定了策略能否“吃饱吃好”。
数据源连接器(Connector)
对于加密货币,常用的Python库有
ccxt
,它统一了数百家交易所的API。我的做法是封装一个
ExchangeDataClient
类,内部使用
ccxt
,但对外提供统一的异步接口。
import asyncio
import ccxt.async_support as ccxt_async
from typing import Dict, List, Optional
import pandas as pd
class ExchangeDataClient:
def __init__(self, exchange_id: str, api_key: str = '', secret: str = ''):
exchange_class = getattr(ccxt_async, exchange_id)
self.exchange = exchange_class({
'apiKey': api_key,
'secret': secret,
'enableRateLimit': True, # 必须启用限流!
'options': {'defaultType': 'spot'} # 或 'future'
})
self.symbols_info = {} # 缓存交易对信息
async def fetch_ohlcv(self, symbol: str, timeframe: str = '1m', limit: int = 100) -> pd.DataFrame:
"""获取K线数据并转为DataFrame"""
try:
ohlcv = await self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df.set_index('timestamp', inplace=True)
return df
except Exception as e:
# 这里需要详细的错误处理和重试逻辑
self.logger.error(f"Failed to fetch OHLCV for {symbol}: {e}")
# 可能触发重试或报警
return pd.DataFrame()
async def close(self):
await self.exchange.close()
实时数据流(Streaming)
对于高频或对延迟敏感的策略,WebSocket是必须的。
ccxt
不直接支持WebSocket,需要用到交易所官方的SDK或第三方库,如
websockets
、
aiohttp
进行连接。这里的关键是
连接管理和断线重连
。你必须假设网络连接是不稳定的,重连逻辑要健壮。
# 伪代码示例:一个简单的WebSocket客户端框架
class WebSocketClient:
def __init__(self, url: str):
self.url = url
self.ws = None
self.connected = False
async def connect(self):
while True:
try:
self.ws = await websockets.connect(self.url)
self.connected = True
await self.on_connected()
async for message in self.ws:
await self.on_message(message)
except (websockets.ConnectionClosed, ConnectionError) as e:
self.connected = False
self.logger.warning(f"WebSocket disconnected: {e}. Reconnecting in 5s...")
await asyncio.sleep(5)
except Exception as e:
self.logger.error(f"Unexpected error: {e}")
await asyncio.sleep(10)
async def on_connected(self):
# 连接成功后,订阅需要的频道
subscribe_msg = {"method": "SUBSCRIBE", "params": ["btcusdt@kline_1m"], "id": 1}
await self.ws.send(json.dumps(subscribe_msg))
async def on_message(self, message: str):
data = json.loads(message)
# 解析数据,并放入一个异步队列(AsyncQueue)中,供其他模块消费
await self.data_queue.put(data)
数据缓存与持久化 不要每次都从交易所拉取全部历史数据。使用本地数据库(如SQLite、PostgreSQL或更专业的时序数据库InfluxDB)缓存K线、tick数据。这能极大提升回测和策略初始化的速度。一个简单的模式是:启动时从数据库加载最近N天的数据,运行时用WebSocket实时数据更新内存和数据库。
3.2 策略层:逻辑与状态的封装
策略层是整个系统的“大脑”。一个好的策略类设计应该清晰地将 参数 、 状态 和 逻辑 分开。
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Any, Dict, List
import pandas as pd
@dataclass
class TradeSignal:
"""交易信号数据类"""
symbol: str
direction: str # 'LONG' / 'SHORT' / 'EXIT'
order_type: str # 'MARKET' / 'LIMIT'
quantity: float
suggested_price: Optional[float] = None # 对于限价单
signal_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
timestamp: pd.Timestamp = field(default_factory=pd.Timestamp.now)
class BaseStrategy(ABC):
"""所有策略的基类"""
def __init__(self, name: str, params: Dict[str, Any]):
self.name = name
self.params = params # 策略参数,可从配置文件加载
self.position = 0.0 # 当前仓位,正数为多,负数为空
self.equity_curve = [] # 权益曲线记录
self.signals: List[TradeSignal] = [] # 产生的信号记录
@abstractmethod
async def on_bar(self, bar: pd.DataFrame):
"""
核心方法:当接收到新的K线(或其他数据)时调用。
bar: 包含最新周期数据的DataFrame,通常包含'open','high','low','close','volume'等列。
"""
pass
@abstractmethod
async def on_order_update(self, order_update: Dict[str, Any]):
"""当订单状态更新时调用,用于更新策略内部仓位状态"""
pass
def generate_signal(self, **kwargs) -> Optional[TradeSignal]:
"""根据策略逻辑生成信号对象"""
# 这里封装信号生成的通用逻辑,比如设置signal_id等
signal = TradeSignal(**kwargs)
self.signals.append(signal)
return signal
一个简单的双均线策略示例:
class MovingAverageCrossover(BaseStrategy):
def __init__(self, name: str, fast_period: int = 10, slow_period: int = 30):
params = {'fast_period': fast_period, 'slow_period': slow_period}
super().__init__(name, params)
self.fast_ma = None
self.slow_ma = None
self.data_window = [] # 用于计算均线的数据窗口
async def on_bar(self, bar: pd.Series):
# bar是一个包含最新价格数据的Series
self.data_window.append(bar['close'])
if len(self.data_window) < self.params['slow_period']:
return # 数据不足,不计算
# 计算均线
df_window = pd.Series(self.data_window)
self.fast_ma = df_window[-self.params['fast_period']:].mean()
self.slow_ma = df_window[-self.params['slow_period']:].mean()
# 金叉买入,死叉卖出(这里简化逻辑,未考虑已有仓位)
if self.fast_ma > self.slow_ma and self.position <= 0:
# 产生买入信号
signal = self.generate_signal(
symbol='BTC/USDT',
direction='LONG',
order_type='MARKET',
quantity=0.001 # 假设买0.001个BTC
)
return signal
elif self.fast_ma < self.slow_ma and self.position >= 0:
# 产生卖出信号
signal = self.generate_signal(
symbol='BTC/USDT',
direction='EXIT', # 平仓
order_type='MARKET',
quantity=abs(self.position)
)
return signal
return None
实操心得 :策略类的
on_bar方法应该保持轻量。复杂的指标计算可以提前在数据层处理好,或者使用pandas的滚动窗口函数高效计算。避免在策略逻辑中进行繁重的循环计算,这会影响事件循环的响应速度。
3.3 风控层:生存高于一切
风控是交易系统的“免疫系统”。没有风控的策略,就像没有刹车的赛车。风控应该作为独立的服务,对所有策略发出的信号进行 强制检查 。
核心风控规则举例:
- 仓位风控 :单一标的仓位不超过总资产的X%;总仓位杠杆倍数不超过Y倍。
- 单笔风险风控 :单笔订单的预计亏损(基于入场价和止损价计算)不超过总资金的Z%。
- 日内交易次数限制 :防止过度交易。
- 最大回撤止损 :当账户总权益从峰值回撤超过一定比例时,强制平仓所有头寸并停止所有策略。
- 时间风控 :不在流动性差的时间段(如周末、节假日)开新仓。
风控层的实现可以是一个规则引擎,按顺序应用一系列风控规则。每个规则都是一个独立的类,实现一个
check(signal, context)
方法,返回
(passed: bool, message: str, modified_signal: Optional[TradeSignal])
。
class MaxPositionRiskRule:
"""最大仓位风险规则"""
def __init__(self, max_single_position_pct: float = 0.1):
self.max_pct = max_single_position_pct
async def check(self, signal: TradeSignal, context: RiskContext) -> RiskResult:
# context 包含当前账户总权益、各标的仓位等信息
account_equity = context.total_equity
proposed_position_value = signal.quantity * context.get_current_price(signal.symbol)
if proposed_position_value / account_equity > self.max_pct:
# 超过限制,可以拒绝,也可以按最大比例修改数量
allowed_qty = (account_equity * self.max_pct) / context.get_current_price(signal.symbol)
if allowed_qty <= 0:
return RiskResult(passed=False, message=f"Position would exceed {self.max_pct*100}% of equity, rejected.")
# 修改信号数量
modified_signal = copy.deepcopy(signal)
modified_signal.quantity = allowed_qty
return RiskResult(passed=True, message=f"Quantity adjusted to {allowed_qty:.4f}", modified_signal=modified_signal)
return RiskResult(passed=True, message="Passed")
3.4 执行层:从信号到订单的“最后一公里”
执行层负责与交易所“对话”。它的挑战在于处理网络延迟、订单部分成交、滑点、交易所限制等现实问题。
订单生命周期管理
一个订单从创建到结束,会经历多种状态:
NEW
->
PARTIALLY_FILLED
->
FILLED
或
NEW
->
CANCELED
/
REJECTED
。执行层需要维护一个订单簿,跟踪每个订单的状态,并及时将状态更新反馈给策略和风控层。
智能订单路由(SOR)与执行算法 对于大额订单,直接下市价单会造成巨大滑点。执行层可以集成简单的执行算法:
- TWAP(时间加权平均价格) :将大单拆分成许多小单,在指定时间段内均匀下单。
- VWAP(成交量加权平均价格) :根据历史成交量分布来规划下单节奏,力求接近市场平均成交价。
实现这些算法需要获取实时盘口(Order Book)数据,并动态调整下单计划。
一个简化的订单管理器示例:
class OrderManager:
def __init__(self, exchange_client):
self.exchange = exchange_client
self.pending_orders: Dict[str, Dict] = {} # order_id -> order_info
async def execute_signal(self, signal: TradeSignal) -> str:
"""执行交易信号,返回订单ID"""
try:
# 根据信号类型构造订单参数
order_params = {
'symbol': signal.symbol.replace('/', ''),
'side': 'buy' if signal.direction in ['LONG', 'EXIT_LONG'] else 'sell',
'type': signal.order_type.lower(),
'amount': signal.quantity,
}
if signal.order_type == 'LIMIT' and signal.suggested_price:
order_params['price'] = signal.suggested_price
# 调用交易所API下单
order = await self.exchange.create_order(**order_params)
order_id = order['id']
self.pending_orders[order_id] = order
self.logger.info(f"Order placed: {order_id} for signal {signal.signal_id}")
return order_id
except Exception as e:
self.logger.error(f"Failed to execute signal {signal.signal_id}: {e}")
raise
async def poll_order_status(self):
"""定期轮询或通过WebSocket监听订单状态更新"""
for order_id in list(self.pending_orders.keys()):
try:
updated_order = await self.exchange.fetch_order(order_id, self.pending_orders[order_id]['symbol'])
# 检查状态是否变化
if updated_order['status'] != self.pending_orders[order_id]['status']:
self.pending_orders[order_id] = updated_order
# 发布订单更新事件,通知策略和风控层
await self.event_bus.publish('order_update', updated_order)
# 如果订单已完成或取消,从pending中移除
if updated_order['status'] in ['closed', 'canceled', 'expired', 'rejected']:
self.pending_orders.pop(order_id, None)
except Exception as e:
self.logger.warning(f"Failed to poll order {order_id}: {e}")
4. 系统集成与事件驱动架构
4.1 事件总线(Event Bus)模式
如何让数据层、策略层、风控层、执行层这些松耦合的模块高效通信?答案是 事件驱动架构 。我们可以引入一个轻量级的“事件总线”(或消息队列)作为中枢。
-
生产者
:数据模块生产
MarketDataEvent,策略模块生产SignalEvent,执行模块生产OrderUpdateEvent。 -
消费者
:策略模块订阅
MarketDataEvent,风控模块订阅SignalEvent,策略和风控模块订阅OrderUpdateEvent。
使用
asyncio
的
Queue
可以简单实现一个进程内的事件总线。对于更复杂的分布式系统,可以考虑
Redis Pub/Sub
或
RabbitMQ
。
import asyncio
from typing import Any, Callable, Dict
import inspect
class AsyncEventBus:
def __init__(self):
self._subscribers: Dict[str, list[Callable]] = {}
def subscribe(self, event_type: str, callback: Callable):
if event_type not in self._subscribers:
self._subscribers[event_type] = []
self._subscribers[event_type].append(callback)
async def publish(self, event_type: str, data: Any):
if event_type in self._subscribers:
for callback in self._subscribers[event_type]:
# 如果回调是协程,则await
if inspect.iscoroutinefunction(callback):
await callback(data)
else:
callback(data)
# 使用示例
event_bus = AsyncEventBus()
# 策略订阅K线事件
async def on_new_bar(bar_data):
print(f"Strategy received bar: {bar_data}")
event_bus.subscribe('new_bar', on_new_bar)
# 数据模块发布事件
async def data_handler():
while True:
bar = await get_new_bar_from_exchange()
await event_bus.publish('new_bar', bar)
4.2 主循环与异步编程
现代交易系统必须是异步的。同步的
time.sleep()
会阻塞整个程序,导致错过重要的市场事件或订单更新。
asyncio
是Python中构建异步并发程序的标准库。
系统的主循环可能长这样:
import asyncio
class TradingAgent:
def __init__(self):
self.event_bus = AsyncEventBus()
self.data_client = ExchangeDataClient('binance')
self.strategies = [MovingAverageCrossover('MA_Strategy')]
self.risk_engine = RiskEngine()
self.order_manager = OrderManager(self.data_client)
self._running = False
async def run(self):
self._running = True
# 启动各个服务任务
data_task = asyncio.create_task(self._run_data_stream())
strategy_task = asyncio.create_task(self._run_strategies())
risk_task = asyncio.create_task(self._run_risk_engine())
order_task = asyncio.create_task(self._run_order_manager())
# 等待所有任务(实际上会一直运行直到被取消)
await asyncio.gather(data_task, strategy_task, risk_task, order_task)
async def _run_data_stream(self):
while self._running:
# 获取数据并发布事件
# ...
await asyncio.sleep(0.1) # 短暂让出控制权
async def _run_strategies(self):
# 订阅数据事件,并处理
self.event_bus.subscribe('new_bar', self._on_bar_for_strategies)
# ...
async def _on_bar_for_strategies(self, bar):
for strategy in self.strategies:
signal = await strategy.on_bar(bar)
if signal:
await self.event_bus.publish('new_signal', signal)
async def _run_risk_engine(self):
self.event_bus.subscribe('new_signal', self._on_signal_for_risk)
# ...
async def _run_order_manager(self):
self.event_bus.subscribe('approved_signal', self._on_signal_for_execution)
# ...
5. 回测与实盘的无缝切换
5.1 回测引擎的设计
在将策略投入实盘前,必须进行严格的历史回测。一个优秀的框架应该能让同一套策略代码,在回测和实盘模式下几乎无需修改即可运行。关键在于 抽象数据源和执行接口 。
-
回测数据源
:从CSV文件或数据库读取历史K线,并按时间顺序“播放”给策略,模拟
on_bar事件。 - 回测执行器 :模拟交易所。当策略发出信号时,不调用真实的API,而是根据历史数据中的下一个时间点的价格(或使用更复杂的模型考虑滑点、手续费)来“成交”,并更新模拟的账户余额和仓位。
-
绩效分析
:回测结束后,需要计算一系列指标:夏普比率、最大回撤、年化收益率、胜率、盈亏比等。
pyfolio和empyrical是不错的库。
回测模式下的主循环伪代码:
class BacktestEngine:
def __init__(self, strategy, historical_data):
self.strategy = strategy
self.data = historical_data # 按时间排序的DataFrame
self.current_index = 0
self.sim_account = SimulatedAccount(initial_capital=10000)
async def run(self):
for i in range(len(self.data)):
bar = self.data.iloc[i]
# 1. 更新策略
signal = await self.strategy.on_bar(bar)
# 2. 模拟风控(可选,可以简化)
# 3. 模拟执行
if signal:
fill_price = self._simulate_fill(signal, bar) # 根据bar的OHLC模拟成交价
self.sim_account.execute_trade(signal, fill_price)
# 4. 记录权益
self.sim_account.update_equity(bar['close'])
self.current_index += 1
# 5. 生成报告
report = self.generate_performance_report()
return report
5.2 实盘部署与监控
实盘部署是另一个挑战。你需要考虑:
- 部署环境 :使用云服务器(如AWS EC2, Google Cloud VM),确保网络稳定、延迟低。建议选择离交易所服务器地理位置近的区域。
-
进程管理
:使用
systemd或supervisor来管理你的交易进程,确保崩溃后能自动重启。 -
配置管理
:策略参数、API密钥、风控规则等必须通过配置文件(如
config.yaml)或环境变量管理, 绝对不要 硬编码在代码里。 -
日志与监控
:使用
logging模块记录不同级别(INFO, WARNING, ERROR)的日志。集成Prometheus和Grafana可以可视化关键指标(如账户权益、仓位、每秒信号数)。设置关键错误报警(如连接断开、风控触发)到Telegram或钉钉。 - 版本控制 :使用Git管理代码。每次实盘部署前打上清晰的Tag。
6. 常见陷阱与进阶优化
6.1 新手常踩的坑
-
未来函数(Look-ahead Bias)
:在回测中,不小心使用了“未来”的数据。例如,在t时刻计算指标时,用到了t+1时刻的收盘价。确保在回测中,
on_bar(bar)函数只能访问到当前bar及之前的数据。 - 幸存者偏差(Survivorship Bias) :回测只使用了目前还存在的交易对,忽略了那些已经下架、归零的币种,导致回测结果过于乐观。回测样本应尽可能覆盖历史全貌。
- 忽略手续费和滑点 :实盘交易有手续费,大额订单会有滑点成本。回测中必须加入这些成本模型,否则结果会严重失真。一个简单的做法是,在成交价上加上一个固定比例(如0.1%)的滑点,并对每笔交易扣除手续费。
- 过度拟合(Overfitting) :在历史数据上反复优化参数,得到一个表现完美的策略,但在未来(或样本外)数据上表现糟糕。避免使用太多参数,进行交叉验证,并在更长的历史周期和不同的市场环境中测试策略的稳健性。
- 网络与API可靠性 :实盘中网络抖动、交易所API限流或临时故障是常态。你的代码必须有完善的 重试机制 、 异常处理 和 心跳检测 。对于关键操作(如下单),要实现指数退避的重试逻辑。
6.2 性能与稳定性优化
-
使用向量化计算
:在策略中,尽量避免在Python层用
for循环处理pandasDataFrame或numpy数组。尽量使用内置的向量化操作,速度可能有百倍提升。 -
异步I/O
:如前所述,整个系统应构建在
asyncio之上,确保高并发下依然响应迅速。 -
内存管理
:长时间运行的系统要注意内存泄漏。定期清理不再需要的历史数据缓存。对于高速tick数据,考虑使用
numpy数组或专门的高性能数据结构。 -
策略热重载
:在不重启主进程的情况下,动态更新策略参数甚至替换策略逻辑。这可以通过将策略代码模块化,并使用
importlib重新加载模块来实现。 - 多进程与分布式 :当策略数量非常多或计算极其复杂时,可以考虑将策略运行在独立的进程中,甚至分布到多台机器上,通过消息队列(如ZeroMQ, Redis)与核心引擎通信。
构建一个成熟的交易智能体框架是一个持续迭代的过程,它没有终点。从最简单的单策略、单交易所版本开始,逐步添加风控、监控、多策略支持、多交易所对冲等功能。这个框架本身不会让你赚钱,但它能让你更高效、更科学、更安全地去验证和实现你的交易想法,将你从重复的底层工程中解放出来。记住,在实盘投入真金白银之前,请务必用历史数据充分回测,并用极小资金进行长时间的模拟盘或实盘试运行,观察策略在真实市场环境下的表现。
更多推荐




所有评论(0)