☰
从零手写Python期货量化回测框架:掌控每个交易环节
2026/10/10 14:11:31 网站建设 项目流程

"Python期货量化策略回测框架",乍一听像是又要推荐backtrader或者vnpy的配置教程。但我这次想讲的恰恰相反:不用任何现成的回测框架,完全从零手写一套能跑起来的期货策略回测系统。为什么这么干?因为我在用现成框架踩了足够多的坑之后发现,回测的价值不在于"能出曲线图",而在于你能完全掌控从行情数据到最终成交的每一个环节。自己写一遍,比读十篇框架文档都管用。这篇内容适合两类人:一是刚学Python、想搞懂量化交易底层逻辑的初学者;二是已经用现成框架写策略、但总感觉黑盒效应明显、想亲手拆解回测引擎的老玩家。我会把数据组织、信号生成、撮合、资金管理、绩效统计的完整链路一步步拆开来讲,并附上可以直接跑的代码思路。

1. 为什么放着现成的框架不用,偏要从零搭一套

很多人的第一反应是:Python里做回测不是有backtrader、zipline、vnpy吗?安装完调用一下就能出结果,何必重复造轮子。

这个质疑很合理,但问题恰恰出在"调用一下"上。我最初也是这么干的,拿backtrader跑一个双均线策略,几分钟就拿到了收益曲线,心里还挺得意。可当我想往策略里加一点更贴近实盘逻辑的东西,比如主力合约切换、保证金动态调整、单笔止损后暂停开仓N根K线,马上发现框架层面的限制一个接一个浮出来:回调函数的执行时机、订单状态机的流转规则、内置broker的撮合细节,每一个都需要翻源码去确认。到最后,我花在"绕开框架限制"上的时间,比写策略逻辑本身还多。

自建回测框架能换来什么,我总结成四点:

  • 每一行逻辑都可控:行情点是怎么走的、成交价落在哪里、手续费怎么扣,整个链路都在自己手里,出了问题立刻能定位。
  • 策略逻辑和引擎解耦:策略只是往引擎里塞信号,引擎只负责撮合和记账。想换策略就换策略,想换撮合规则就换撮合规则。
  • 真实吃透交易流程:手写一遍撮合和记账之后,你会真正理解"成交""持仓""权益"这些词汇背后的准确含义,这对实盘交易的理解有直接帮助。
  • 方便按期货特性深度定制:期货的换月、涨跌停、保证金率调整、强平逻辑,这些在通用框架里往往只是简化处理,自己写可以做到逐项仿真。

那是不是说现成框架就没用了?不是。backtrader这类框架最大的价值在于它帮你抽象了"策略层"的通用结构,很多简单策略拿来就能跑,做快速验证很合适。但如果你想深入理解回测结果为什么长这样,或者你的策略涉及期货特有的边界条件,我的建议是至少在本地实现过一遍自己的回测流水线。

从成本角度算一笔账:自建一套最小可用的回测引擎,核心代码量其实就几百行。相比在框架的坑里爬两星期,这笔投入远比你想象的值。

2. 先想清楚回测引擎的骨架:数据怎么流,状态怎么变

动手写代码之前,最重要的不是急着import pandas,而是把整个回测系统的数据流和状态流画出来。这一步想清楚,后面写代码就是填肉的事。

一个期货策略回测系统,本质上是一个事件驱动的状态机。行情数据逐笔或逐Bar地进入系统,系统根据当前策略判断要不要下单,然后经过撮合逻辑变成成交,最终更新账户状态。整个流程可以拆成五个环节:

  1. 行情订阅:拿到期货合约的历史K线或tick数据,按时间顺序一条条喂给引擎。
  2. 信号生成:策略根据当前持仓和历史行情计算指标,输出目标仓位方向,比如"开多1手"或"平掉此前空单"。
  3. 订单生成:把策略信号转成标准的订单对象,记录合约、方向、价格、手数、下单时间。
  4. 撮合成交:对订单按当根Bar或下一个Bar的开盘价、收盘价等规则撮合,计算出实际成交价、成交量和滑点损耗。
  5. 账户更新:更新持仓、保证金、已实现盈亏、浮动盈亏、可用资金等状态。

整个系统的核心数据流大致是这样的:K线数据进来 → 指标更新 → 策略出信号 → 订单进入撮合 → 成交回报 → 账户状态更新 → 净值曲线多一个点 → 下一根K线进来。这个循环会一直持续到数据结束。

这里有一个非常关键的设计决策:事件驱动回测还是向量化回测。向量化的思路是把整个持仓序列一次性算出来,再逐日计算收益,速度快、代码短,适合股票类单品种策略。但期货策略常常涉及逐笔成交、保证金加减仓、强制平仓这类时序状态,向量化很难表达清楚,所以我建议采用事件驱动的逐Bar循环,虽然慢一点,但每笔成交和资金变化都有清晰的时间脉络,排查起来清清楚楚。

K线数据用什么结构组织也有讲究。我常年在项目中用pandas的DataFrame来存原始行情,但在引擎内部会把每一根Bar转成Python对象再传入循环。这里不需要用复杂的高性能队列,普通的列表加索引就能撑住几万根Bar的回测,Python解释器在这个量级下性能完全不是瓶颈。

还有一点很重要:千万不要在回测循环里去算未来数据。比如一根Bar的开盘价只在它出现的那一刻可用,你在当根Bar收盘前就用当根Bar的最低价去判断止损,这在回测里看着赚钱,实盘里根本做不到。这个问题我会在后面的"坑"那一节详细展开。

3. 搭建引擎核心模块:数据层、策略层和撮合层怎么协作

现在进入正题。我从零搭回测引擎时,把代码拆成四个文件:data_feed.py负责数据读入和标准化,strategy.py定义策略基类和信号输出,broker.py负责撮合和记账,engine.py跑主循环。当然你也可以放在一个文件里,但分层是好习惯,尤其当你后面想把它扩到模拟盘时,分层能省下大量重构时间。

3.1 数据层:先把行情喂进去

第一步是保证所有合约的数据格式统一。我的做法是把原始数据规整成一个包含datetime, open, high, low, close, volume, open_interest的DataFrame,然后写一个简单的迭代器,让主循环能按时间顺序逐个取Bar。

# data_feed.py import pandas as pd from dataclasses import dataclass @dataclass class Bar: dt: pd.Timestamp open: float high: float low: float close: float volume: float open_interest: float class DataFeed: def __init__(self, df): self.df = df.reset_index(drop=True) self.idx = 0 def __iter__(self): return self def __next__(self): if self.idx >= len(self.df): raise StopIteration row = self.df.iloc[self.idx] self.idx += 1 return Bar(dt=row['datetime'], open=row['open'], high=row['high'], low=row['low'], close=row['close'], volume=row['volume'], open_interest=row['open_interest'])

这里要单独提一下持仓量open_interest。期货和股票最大的不同之一,就是持仓量是个动态数据,它会直接影响你的资金占用和强平风险。比如螺纹钢的持仓量突然暴增,往往意味着多空博弈加剧,你的保证金占用也可能随之变化。如果你的策略逻辑依赖持仓量数据,回测时就一定要保证该字段的准确性,否则资金计算会有偏差。

3.2 策略层:只负责产出信号

策略层是整个系统里最灵活的部分,我的设计思路是让它只做一件事:根据当前Bar和持仓状态,返回一个或多个"目标操作"。这些操作是纯描述性的,比如OpenLong(1),CloseShort(),OpenShort(2),CloseAll()等,不涉及价格到底怎么成交。

# strategy.py from dataclasses import dataclass from typing import List @dataclass class Signal: action: str # 'open_long', 'close_long', 'open_short', 'close_short' size: float = 1 # 手数/张数 tag: str = '' # 备注,比如触发了哪一条规则 class BaseStrategy: def __init__(self): self.positions = {} # 由引擎注入当前持仓状态 def on_bar(self, bar) -> List[Signal]: raise NotImplementedError

之所以要把持仓状态注入到策略里,是因为很多策略的买卖决策依赖于当前是否空仓、持有多头还是空头、持仓周期有多长等。策略自己保存这些状态也可以,但由引擎统一管理,可以避免策略在回测循环里被意外重置时丢失状态。

我在最开始写策略时,常常把"下单逻辑"直接写在信号生成里,比如在on_bar里直接减掉手续费、直接算成交价,结果导致策略和撮合逻辑纠缠不清,改起参数来非常痛苦。所以请一定坚持:策略说目标,撮合定事实。

3.3 撮合层:订单变成成交的地方

撮合层是整个回测系统里最能体现"仿真度"的模块。最简单的撮合规则是:当根Bar收盘后,按下根Bar的开盘价成交。这个规则在期货策略回测里非常常用,因为它假设信号是在收盘后产生的,实盘里你下单也只能等下一个行情瞬间成交。

实际上,具体用哪种价格成交,取决于你的策略类型:

  • 收盘信号开盘成交:稳妥,最常见,没有未来函数嫌疑。
  • 即时价成交:比如在盘中触发了条件单,就以当前Bar的某个价格成交,但要注意你是不是真的能在这个价格拿到流动性。
  • 最优价/主动吃单:如果策略假设自己以市价单方式主动吃盘口,成交价可能等于对手价,可以考虑加一个滑点。

先给一个最朴素的撮合逻辑,它按下根Bar开盘价成交,并考虑固定滑点:

# broker.py class Broker: def __init__(self, init_cash, commission_rate=0.0, slippage=0.0): self.cash = init_cash self.position = 0 # 正数表示多仓,负数表示空仓,单位是手 self.entry_price = 0.0 self.commission_rate = commission_rate self.slippage = slippage def place_order(self, action, signal_size, next_open): fill_price = next_open + self.slippage * (1 if action in ['open_long', 'close_short'] else -1) # 计算手续费,期货常见按成交额比例或按手数 # 这里演示按手数的简化版,具体在后面章节细讲 # 更新持仓和现金

这个伪装不完整的逻辑后面会补全。但核心思想是:撮合层拿到策略信号后,立刻计算成交价、手续费、持仓变化和现金变化,然后把结果记录到交易流水里。只有把这两个动作绑在一起,账户状态才始终是一致的。

3.4 主引擎:把上面几个模块串起来

主引擎就是一个循环,它不断从DataFeed里取Bar,先更新策略的持仓视图,再调用策略的on_bar拿到信号,接着把信号送进Broker撮合,最后记录当期的净值。

# engine.py class Engine: def __init__(self, data_feed, strategy, broker): self.feed = data_feed self.strategy = strategy self.broker = broker self.equity_curve = [] def run(self): for bar in self.feed: self.strategy.positions = self.broker.get_positions() signals = self.strategy.on_bar(bar) if signals: for sig in signals: self.broker.place_order(sig, bar) equity = self.broker.get_equity(bar.close) self.equity_curve.append((bar.dt, equity))

注意这里有一个细节:我在每个Bar结束时都调用get_equity(bar.close),它会把未平仓持仓按照当前收盘价重新估值,加上现金,然后作为该时间点的总权益。这一步就是净值曲线的来源。很多刚入门的朋友只算已实现盈亏,导致平仓前的净值一直是一条水平线,完全看不出浮动亏损,这是不对的。

4. 期货交易成本的仿真:手续费、滑点和保证金

回测里最容易被美化、也最影响最终结论的就是交易成本。很多策略在理论状态下收益漂亮的惊人,一加上手续费和滑点立刻变脸。这一节我们把期货特有的一整套成本结构讲清楚。

4.1 手续费:按手数还是按成交额

期货手续费有两种计费方式。一种是按手数固定收取,比如螺纹钢每手10元;另一种是按成交金额的比例,比如铁矿石按成交额的万分之几。部分品种是两者结合,比如先按固定金额,再加一定比例。我在写手续费模块时会用一个配置字典来区分品种和合约:

COMMISSION_CONFIG = { 'RB': {'mode': 'per_lot', 'value': 10.0}, # 螺纹钢每手10元 'I': {'mode': 'by_ratio', 'value': 0.0002}, # 铁矿万二 }

需要注意的是,期货手续费在开仓和平仓时往往不对称,有的品种平今仓(当天开当天平)费用更高。如果在回测里不做区分,你的日内策略成本会被严重低估。我早期跑螺纹钢高频策略时,就是忽略了平今仓惩罚,回测收益率比实盘高了两倍还多,后来逐笔对比实盘账单才发现。

4.2 滑点:最朴素的建模

滑点可以理解为你的订单实际成交价和看到的价格之间的差距。在回测里最常见的三种建模方式:

  • 固定滑点:买卖都直接加一个绝对值或最小变动价位倍数,比如螺纹钢每次成交多滑1个tick(1元/吨)。
  • 比例滑点:按成交价格的一定比例加滑点,比如0.02%。
  • 流动性冲击模型:根据你的下单量占市场成交量的比例来估算冲击成本,比如下单量超过该Bar成交量的5%,滑点会显著上升。

第三种最贴近实盘,但对数据要求高。我个人通常在实盘初期用一个保守的固定滑点+比例滑点组合。比如螺纹钢,成交价按期货盘面价格加2个tick,同时再按成交额的万之0.5增加摩擦成本。这比单用固定滑点更保险。

4.3 涨跌停、停板和流动性过滤

期货有涨跌停板制度,一旦价格封在涨跌停板上,很多时候你根本成交不了。回测时如果忽略这一点,止损单在跌停板上撮合成功,而实盘里可能根本跑不掉,这是最危险的误差之一。我建议至少做一层防护:如果当根K线的开盘价或最低价触碰了涨跌停价,那么以该方向成交的订单是否还能成交,要打一个问号。

更精细的做法是看成交量。如果某根Bar的成交量极低,说明市场流动性差,假设你能顺利成交几百手单子往往不符合现实。可以在撮合规则里加一个"成交量约束":当订单量超过当前Bar成交量的某个倍数时,按可成交比例部分成交,剩下部分继续挂单等待后续Bar。

我当时的做法是给策略一个fill_ratio概念:比如螺纹钢某根Bar成交量为2万手,策略想开多500手,这占25%,在市况正常时还能接受,但在接近涨跌停时我会强制把成交比例降到0。这种细节看起来麻烦,但能有效避免回测曲线在极端行情下"假翻倍"。

4.4 期货特有的保证金和强制平仓

期货是保证金交易,你不需要支付合约全额,只需要支付一定比例的资金作为担保。不同的品种保证金率不同,通常在5%-15%之间,而且交易所会根据市场风险调整保证金率。

在账户模块里,我维护了以下几个核心字段:

  • cash:现金余额,包含已实现盈亏和可用资金。
  • position:当前持仓手数,正数多头、负数空头。
  • entry_price:开仓价格,用于计算浮动盈亏。
  • margin:当前占用保证金。
  • equity:总权益,等于现金加浮动盈亏。

保证金计算公式是:持仓手数 × 合约乘数 × 当前价 × 保证金比例。比如螺纹钢一手合约是10吨/手,价格4000元/吨,保证金率10%,那么开一手需要占用的保证金就是1 × 10 × 4000 × 10% = 4000元。

强制平仓逻辑也必须在回测里实现。当账户的风险度(当前占用保证金/总权益)超过某个阈值时,交易所或期货公司会要求追加保证金,达不到就强平一部分仓位。在自建框架里,我会在每次更新账户状态后检查风险度,如果超过阈值,就按从后往前减仓的顺序平掉部分持仓,把风险度拉回安全线。没有这层逻辑,你的回测在极端行情下可能会出现负权益还在继续运行的荒诞结果。

5. 资金管理与绩效统计:回测结果为什么不能只看收益率

一个回测系统跑完,最重要的产出是一串净值数据和一系列绩效指标。但很多人习惯只看"总收益率",然后等着实盘打脸。这一节我讲讲怎么把绩效统计做得扎实一点。

5.1 净值曲线的正确画法

净值曲线的逻辑是:每个Bar结束后,用当天结算价(或收盘价)重新估值整个账户,得到一个总权益。把每一天或每一根Bar的总权益连成一条线,就是净值曲线。这里有个容易犯的错误:有人用"初始资金 + 每笔平仓盈亏"来画,这导致持仓期间的浮动浮亏不体现在曲线上,看起来非常平滑,实际毫无参考价值。

正确的做法我已经在引擎代码里体现过了:每个Bar结束时,用当前收盘价把未平仓持仓重新标记为市值。如果当前是多头持仓,市值 = 持仓手数 × 合约乘数 × 当前价,总权益 = 现金 + 浮动盈亏。这样画出来的曲线才和真实账户的每日盯市一致。

5.2 必算的核心绩效指标

我在回测结果里固定输出一组指标,每个指标的计算逻辑如下:

  • 累计收益率:(期末权益 - 初始权益) / 初始权益。
  • 年化收益率:累计收益率 × (每年Bar数 / 总Bar数),如果是日线数据,直接用252个交易日估算。
  • 最大回撤:从净值的局部高点一路跌到后续某个低点的最大幅度。注意要使用"从最高点到之后最低点"的严格定义,而不是简单地拿最高值和最低值做差。
  • 夏普比率:(策略年化收益率 - 无风险利率) / 策略年化波动率。常见做法先算每期收益率的均值和标准差,再年化,尽量避免在样本太少时直接除以很小的波动率。
  • 卡玛比率:年化收益率 / 最大回撤,这个指标在回撤较大的策略里比夏普更有参考意义。
  • 胜率:盈利交易笔数 / 总交易笔数。注意这里的"一笔交易"如何定义,我习惯把一个方向的连续开平仓视为一笔完整交易。
  • 盈亏比:平均每笔盈利金额 / 平均每笔亏损金额。

一个简单的绩效统计函数大概长这样:

# performance.py def max_drawdown(equity_curve): peak = equity_curve[0] max_dd = 0.0 for v in equity_curve: if v > peak: peak = v dd = (peak - v) / peak if dd > max_dd: max_dd = dd return max_dd def sharpe_ratio(daily_returns, rf=0.0): import numpy as np arr = np.array(daily_returns) if len(arr) < 2: return 0.0 excess = arr - rf / 252 return np.sqrt(252) * excess.mean() / excess.std()

5.3 一个"高收益低回撤"的策略为什么可能不真实

假设某策略的日度胜率有60%,年化收益率30%,最大回撤只有5%。看着很美对不对?但如果我去翻它的交易明细,发现总共只交易了20次,其中前15次全赢,后5次全输,最后仍然落在"最大回撤5%"内。这种统计在交易次数极少时毫无意义,它的置信区间太宽了。

我在看回测结果时会额外看几样东西:交易次数是否足够(至少50笔以上)、盈亏分布是否集中在一两笔"神单"上、最大回撤的修复时间是否过长。如果最大回撤只用三天就修复,通常只是运气,而不是能力。很多职业交易者更喜欢用"回撤修复时间"和"连续亏损次数"来衡量策略的稳定性,这两个指标比单纯的收益率更经得起推敲。

5.4 样本内外测试和参数敏感性

回测最怕的就是在历史数据上反复调参,直到找到一组"完美"参数。这种做法本质上是在拟合噪声。我的习惯是把数据切成三段:训练段、验证段、样本外测试段。先在训练段上开发策略、粗调参数,在验证段上微调,最后只在样本外段跑一次,看是否还能维持合理的绩效。如果一个策略在训练段年化50%,到样本外段年化直接变成-5%,基本可以断定它不具备任何预测能力。

另一个有用的做法是参数敏感性分析。找一个核心参数(比如均线周期或止损比例),在它周围做一组等间隔扫描,画出收益和回撤随参数变化的曲线。如果曲线是缓慢平滑的,说明策略对参数不敏感,比较稳健;如果曲线剧烈抖动像锯齿,说明存在严重的过拟合,参数稍微偏移一角,收益就会崩掉。

6. 从回测走向模拟和实盘的工程化思考

回测系统跑通之后,很多人会立刻想把它接到实盘。这里我要泼一盆冷水:回测到实盘之间的鸿沟,往往比你想象的大得多。但从工程角度看,我们可以在设计回测系统时就为将来铺好路。

6.1 把策略逻辑和行情源彻底解耦

我自建框架时特意把数据读取封装成独立的DataFeed类,目的就是将来接实盘时,我可以写一个LiveFeed,它能订阅交易所的实时行情并转化为同样的Bar对象。这样策略层的on_bar代码完全不用改,就能从历史回测平滑切换到模拟盘。

同理,Broker层也要抽象出接口。回测的Broker负责撮合和记账,模拟盘的Broker则负责把订单发到期货公司的模拟柜台,并接收成交回报。只要策略层和两者之间通过标准信号交互,这个替换就是自然而然的。

6.2 Backtrader 这类框架能给我们什么参考

虽然前面说自建框架能把逻辑吃得更透,但在工程化能力上,backtrader这类成熟框架确实值得我们参考。它内置了订单状态机、滑点模型、多品种组合、分析器体系,这些设计很成熟。我在手写框架的过程中,其实是把backtrader的核心抽象——比如用next()驱动逐Bar循环、把订单撮合与策略逻辑分离——手动复刻了一遍。

如果你在做自建框架时遇到某个模块的边界怎么划分的困惑,完全可以去翻backtrader的源码。它不只是一个工具,也是一份很好的"回测引擎设计说明书"。

6.3 最小可用的模拟盘改造方案

如果你想先不面对真实账户,可以从模拟盘开始。现在国内不少期货公司的仿真交易接口都提供Python SDK,甚至支持通过OpenAPI下发订单。改造路径大致是这样:

  • 写一个LiveFeed,周期性地从行情接口获取最新tick,聚合成分钟Bar,然后喂给策略。
  • 写一个SimBroker,把信号转成模拟盘平台的委托单,并监听委托回报和成交回报。
  • 复用原有绩效统计模块,把实时的净值更新到本地数据库或CSV文件里。

这里有个细节值得说:模拟盘的成交回报是异步的,下单和成交之间存在延迟,而且在撤单、拒单、部分成交等场景下,状态流转比回测复杂得多。你需要在回测里提前习惯"订单可能被拒绝""价格没到就不成交"这类现实约束,否则到了模拟盘会手忙脚乱。

7. 实战踩坑清单:写回测系统过程中我最想删掉的代码

最后分享几个我从零搭框架时踩过的比较深的坑,每一个都直接影响了回测结果的可信度,希望你能绕开。

7.1 未来函数:用未来数据洗过去的钱

这是回测里最致命的坑。曾有一个策略,我在计算指标时写了个df['sma'] = df['close'].rolling(10).mean(),然后在循环里用bar.close > df['sma'].iloc[i+1]来判断是否开仓。i+1指向了未来一根K线,等于你在用明天的均线判断今天开不开仓,回测自然赚的飞起,实盘直接亏穿。这种问题在遍历DataFrame时特别隐蔽,一定要养成"当前Bar的数据只用当前及之前数据"的编码习惯。

7.2 幸存者偏差:只看到活下来的品种

如果你回测的是某个品种池,注意品种池里的合约必须是"当时存在"的合约,而不能拿今天还在交易的品种去回测10年前的历史。因为10年前那些后来退市或被边缘化的合约,如果当时没挣到钱,它们的数据往往没人保留。你现在看到的业绩,很可能只是活下来的幸存者的业绩。处理和筛选数据时要特别小心。

7.3 随机数不设种子:不可复现的结果

如果你的策略里用了随机抽样、随机森林或蒙特卡洛模拟,千万记得固定随机种子。否则你每次运行回测都会得到略有不同的结果,很难判断是策略本身在起作用,还是纯粹的随机波动在起作用。我在涉及参数优化时,也会对每个随机种子分别做一组回测,取均值而不是单次结果做判断。

7.4 过拟合:参数永远会骗人

回测系统本身不会让你过拟合,但"在回测上反复试参数"这个行为会。我给自己的规则是:每天只允许在训练集上调三次参数,之后无论结果多差都不许当天再改。这个规则看起来很笨,但能拦住很多手痒乱试的时刻。参数扫描图和样本外测试结果,一定要打印出来留在手边,不是为了发文章,是为了逼自己在实盘前保持冷静。

7.5 实盘前必须自问的五个问题

  • 这个策略在最近一年的样本外数据上表现如何?如果最近三个月亏了,我还敢上实盘吗?
  • 策略的每一笔交易都能从实盘行情中真实复现吗?比如涨停板上开仓、跌停板上平仓,这种交易我能做到吗?
  • 如果连续遇到20次止损,账户最大回撤我能扛住吗?
  • 手续费和滑点假设比实盘激进还是保守?我有没有把平今仓惩罚算进去?
  • 如果策略明天就失效了,我的资金管理和心态能撑到发现这个问题的时候吗?

这些问题没有固定答案,但每一条都值得在实盘前认真写下来回答一遍。很多人在回测里花了大量时间优化入场信号,却很少问自己"如果这个信号失效了我该怎么办",而后者往往才是交易生涯真正分水岭。

我在搭完这套回测框架之后,最大的感触并不是"我掌握了多少Python技巧",而是对期货交易本身多了一层敬畏。回测系统的价值,不只是给你一条漂亮净值曲线,而是逼你在每一行代码里回答:"你的交易逻辑,到底凭什么长期赚钱?"这个问题想得越清楚,框架能给你的东西就越多。你可以从最朴素的双均线开始,把这个框架跑起来,再逐步加入止损、加仓、资金管理、换月处理。等哪天你发现自己已经开始讨论"这个滑点模型在夜盘时段会不会失真"时,你就已经从"用回测"进入"做回测"的阶段了。这个门槛跨过去,真正的策略研究才算刚刚开始。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询