简介:这份PDF是TradeBlazer公式语言的系统参考手册,面向金融量化交易开发者、策略研究员及希望将交易思想转化为可执行代码的软件开发者。它解决的核心问题是:如何用一门语法简洁但功能强大的高级语言,直接处理股票、期货等时间序列数据,并完成技术指标、交易指令与自动化策略的编写。资源包共1个PDF文件,大小约220KB,内容为完整的语言参考文档,便于随时查阅语法、操作符、表达式与控制语句。手册系统梳理了用户函数、用户字段、技术指标、K线型态、特征走势与交易指令六大公式类型,并深入讲解Bar数据体系,包括开盘价、收盘价、最高价、最低价、成交量、持仓量及时间戳等系统函数,以及逐Bar执行、回溯引用、无效值处理等计算机制。读者可借助示例程序掌握公式编写要领,将个人交易逻辑落地为可回测、可自动执行的策略工具。目前已有115人学习,适合作为量化交易入门与进阶的案头参考。
1. TradeBlazer 语言入门:一份 PDF 参照文档到底能帮你解决什么问题
很多人第一次拿到一份名为「TradeBlazer 语言介绍[参照].pdf」的文档时,第一反应是——这不就是个说明书吗?翻两页就扔到一边了。但如果你正在做量化策略开发,尤其是国内期货、证券市场的程序化交易,这份参照文档的价值远比你想象的大。TradeBlazer(简称 TB)是一套面向国内交易者的策略开发语言与运行平台,它的语言设计介于 C 语言风格和领域专用语言之间,语法不复杂,但坑不少。这份 PDF 参照文档本质上是一份语言规范速查手册,覆盖了变量声明、运算符、控制流、内置函数、交易指令等核心内容。
它适合两类人:一类是刚接触 TB 平台、想从零写一个能跑的策略的新手;另一类是从其他平台(比如文华、金字塔)迁移过来,需要快速对照语法差异的老手。这篇文章不会逐页翻译那份 PDF,而是把这份参照文档里最核心的语言要素拆出来,告诉你哪些必须先掌握、哪些可以查着用、哪些地方容易翻车。读完你至少能做到:独立写出一个带开平仓逻辑、带止损、能回测的 TB 策略,并且知道遇到报错时该去参照文档的哪个部分找答案。
2. TradeBlazer 语言的核心语法骨架:从变量到交易指令
2.1 变量声明与数据类型:为什么 TB 不像 C 那样严格
TB 语言的变量声明比 C 宽松得多。你不需要在声明时指定类型,系统会根据赋值自动推断。但宽松不等于没有规则,参照文档里明确列出了几种基本类型:数值型(Numeric)、字符串型(String)、布尔型(Bool)。实际写策略时,绝大多数变量都是数值型,用来存价格、均线值、持仓量等。
// TB 语言变量声明示例 Vars NumericSeries MA5; // 数值序列变量,存均线值 NumericSeries MA20; // 数值序列变量 Numeric MyStopLoss; // 普通数值变量,存止损价 Bool IsLong; // 布尔变量,标记是否持多仓 String StrategyName; // 字符串变量 Begin StrategyName = "均线交叉策略"; MA5 = Average(Close, 5); // 计算5周期收盘均线 MA20 = Average(Close, 20); // 计算20周期收盘均线 MyStopLoss = 0; IsLong = False; End这段代码里最关键的是NumericSeries和Numeric的区别。NumericSeries是序列变量,它会自动保存每一根 K 线上的历史值,你可以用MA5[1]取上一根 K 线的 MA5 值。而Numeric是普通变量,只保留当前值,不保存历史。这个区别在写跨周期引用或条件判断时极其重要——如果你用普通Numeric去存均线值,然后在下一根 K 线上想取前值,就会拿到错误结果。参照文档在变量章节专门用了一个小节讲序列变量和普通变量的差异,但很多人翻文档时直接跳过,结果回测信号和实盘对不上,查半天查不出原因。
参数说明:Average(Close, 5)里的Close是内置的收盘价序列,5是周期数。TB 内置了大量这样的序列函数,比如Open、High、Low、Volume,直接拿来用就行,不需要自己定义。
2.2 运算符与表达式:那些文档里没写清楚的优先级陷阱
TB 的运算符和 C 语言基本一致:+、-、*、/、%、>、<、>=、<=、==、!=、&&、||。但有一个地方参照文档写得比较简略,就是运算符优先级。实际写策略时,条件判断里混用&&和||如果不加括号,很容易出现逻辑和你预期不一致的情况。
// 运算符优先级示例:不加括号的坑 Vars NumericSeries MA5; NumericSeries MA20; Bool Signal; Begin MA5 = Average(Close, 5); MA20 = Average(Close, 20); // 危险写法:&& 和 || 混用不加括号 // 实际执行顺序可能和你想象的不同 Signal = MA5 > MA20 && Close > Open || Volume > 10000; // 安全写法:用括号明确逻辑分组 Signal = (MA5 > MA20 && Close > Open) || Volume > 10000; End血泪经验:我见过不止一个策略因为条件表达式没加括号,导致回测信号比预期多出一倍。TB 的&&优先级高于||,这和 C 语言一致,但很多人写策略时脑子里想的是「满足 A 和 B,或者满足 C」,写出来却是A && B || C,实际执行的是(A && B) || C,逻辑上没错,但如果你的本意是A && (B || C),那就完全跑偏了。参照文档在运算符章节只列了优先级表,没有给混用示例,这个坑得自己踩过才知道。
2.3 控制流语句:If、While、For 在策略里的实际用法
TB 支持If-Else、While、For三种控制流。写策略时最常用的是If-Else,用来做条件判断和分支处理。While和For一般用在需要循环计算的场景,比如遍历历史数据做统计,但 TB 的策略执行模型是逐 K 线运行的,循环用不好容易导致性能问题甚至死循环。
// 控制流示例:带止损的均线策略 Vars NumericSeries MA5; NumericSeries MA20; Numeric MyEntryPrice; Numeric MyStopLoss; Begin MA5 = Average(Close, 5); MA20 = Average(Close, 20); // 开仓条件:金叉且空仓 If (MA5 > MA20 && MA5[1] <= MA20[1] && MarketPosition == 0) Then Begin Buy(1, Close); // 买入1手,以收盘价成交 MyEntryPrice = Close; // 记录入场价 MyStopLoss = MyEntryPrice * 0.98; // 止损设为入场价的98% End // 止损条件:持多仓且价格跌破止损线 If (MarketPosition == 1 && Close < MyStopLoss) Then Begin Sell(1, Close); // 卖出平仓 End // 止盈条件:持多仓且死叉 If (MarketPosition == 1 && MA5 < MA20) Then Begin Sell(1, Close); End End逻辑说明:MarketPosition是 TB 内置变量,返回当前持仓状态,0表示空仓,1表示持多仓,-1表示持空仓。Buy(1, Close)表示以收盘价买入 1 手,Sell(1, Close)表示以收盘价卖出 1 手平仓。注意Buy和Sell是交易指令,不是普通函数,它们会直接触发模拟交易或实盘报单。
参数说明:Buy和Sell的第一个参数是手数,第二个参数是价格。实际写策略时,价格参数可以用Close、Open、High、Low,也可以用NextBarOpen之类的预定义价格。参照文档在交易指令章节列出了所有可用的价格类型,建议写策略前先翻一遍。
3. 用 TB 语言写一个可回测的完整策略:从零到跑通
3.1 策略框架搭建:Vars、Begin、End 三件套
TB 策略的基本结构是固定的:Vars段声明变量,Begin和End之间写逻辑。这个结构看起来简单,但有几个细节容易出错。第一,Vars段里声明的变量名不能和内置变量重名,比如你不能声明一个叫Close的变量,因为Close是内置的收盘价序列。第二,Begin和End必须成对出现,嵌套的If语句里也要用Begin和End包住多行逻辑,否则只有第一行属于If体。
// 完整策略框架示例 Vars NumericSeries FastMA; NumericSeries SlowMA; NumericSeries ATRValue; Numeric MyStopLoss; Numeric MyTakeProfit; Begin // 计算指标 FastMA = Average(Close, 10); SlowMA = Average(Close, 30); ATRValue = AvgTrueRange(14); // 开多仓条件 If (FastMA > SlowMA && FastMA[1] <= SlowMA[1] && MarketPosition == 0) Then Begin Buy(1, Close); MyStopLoss = Close - 2 * ATRValue; // 2倍ATR止损 MyTakeProfit = Close + 3 * ATRValue; // 3倍ATR止盈 End // 止损止盈逻辑 If (MarketPosition == 1) Then Begin If (Low <= MyStopLoss) Then Sell(1, MyStopLoss); // 触发止损 If (High >= MyTakeProfit) Then Sell(1, MyTakeProfit); // 触发止盈 End End逻辑说明:这个策略用双均线交叉开仓,用 ATR 动态设置止损止盈。AvgTrueRange(14)计算 14 周期平均真实波幅,用来衡量市场波动性。止损设为入场价减去 2 倍 ATR,止盈设为入场价加上 3 倍 ATR,这样在不同波动环境下止损止盈距离会自动调整。
参数说明:AvgTrueRange的参数是周期数,常用 14 或 20。Buy和Sell的手数参数可以根据资金量调整,回测时一般先用 1 手跑通逻辑,再根据资金曲线调整仓位。
3.2 回测参数设置:手续费、滑点、保证金怎么填
策略写完后,回测结果的可靠性很大程度上取决于参数设置。TB 的回测设置里有几个关键参数:手续费、滑点、保证金率、合约乘数。这些参数填不对,回测曲线再漂亮也是自欺欺人。
| 参数 | 常见值 | 说明 |
|---|---|---|
| 手续费 | 按手数或按成交额 | 国内期货一般按手数收,比如 5 元/手 |
| 滑点 | 1-2 跳 | 模拟实际成交价和预期价的偏差 |
| 保证金率 | 8%-15% | 不同品种不同,参照交易所标准 |
| 合约乘数 | 10-300 | 比如螺纹钢 10 吨/手,铜 5 吨/手 |
注意:滑点参数最容易被忽略。很多人回测时滑点设 0,结果实盘一跑发现成交价总是比信号价差一两个跳,累积下来吃掉不少利润。我一般会设 1-2 跳的滑点,具体看品种流动性。手续费也要按实际标准填,别为了回测好看故意填低。
3.3 回测结果解读:夏普、最大回撤、胜率哪个更重要
回测跑完后,TB 会输出一堆指标:总收益、年化收益、最大回撤、夏普比率、胜率、盈亏比等。新手最容易盯着总收益看,但总收益高不代表策略好。一个策略如果最大回撤 50%,总收益 100%,另一个策略最大回撤 15%,总收益 60%,后者在实际交易中更可用,因为回撤小意味着资金曲线更平滑,心理压力更小,也更容易坚持执行。
夏普比率衡量的是单位风险带来的收益,一般大于 1 算及格,大于 2 算不错。但夏普比率对回测周期敏感,短周期回测的夏普比率参考价值有限。胜率不是越高越好,胜率 40% 但盈亏比 3:1 的策略,长期下来比胜率 70% 但盈亏比 0.5:1 的策略更赚钱。看回测结果时,我一般先看最大回撤和夏普比率,再看盈亏比,最后才看总收益。
4. TradeBlazer 语言避坑指南:5 个高频翻车现场
4.1 序列变量当普通变量用,回测信号对不上
现象:回测时信号正常,实盘跑起来信号延迟或丢失。原因:把NumericSeries声明成了Numeric,导致历史值丢失,跨周期引用时拿到的是当前值而不是前值。解决:凡是需要取历史值的变量,一律用NumericSeries声明。参照文档在变量章节有明确说明,但很多人写代码时图省事,随手写Numeric,后面出问题查半天。
4.2 交易指令写在条件判断外面,每根 K 线都报单
现象:回测时成交次数异常多,手续费吃掉大量利润。原因:Buy和Sell指令没有放在If条件里,或者If条件写错了,导致每根 K 线都触发交易。解决:交易指令必须放在明确的条件判断里,并且加上MarketPosition检查,确保不会重复开仓。比如If (条件 && MarketPosition == 0) Then Buy(...)。
4.3 循环里引用序列变量,性能急剧下降
现象:策略回测速度极慢,几万根 K 线跑十几分钟。原因:在For或While循环里频繁引用序列变量,每次引用都会触发历史数据查找。解决:把循环里需要用的序列值先赋给普通变量,循环里用普通变量计算。比如Numeric TempMA = MA5;然后在循环里用TempMA。
4.4 止损止盈用 Close 判断,盘中触发不了
现象:回测时止损止盈正常触发,实盘时价格盘中已经穿过止损线但没成交。原因:用Close判断止损止盈,只有收盘价满足条件才触发,盘中价格波动被忽略。解决:用Low和High判断止损止盈,或者用NextBarOpen在下一根 K 线开盘时触发。参照文档在交易指令章节有价格类型说明,建议仔细看一遍。
4.5 参数优化过度,回测漂亮实盘亏损
现象:回测曲线完美,实盘一跑就亏。原因:参数优化时过度拟合历史数据,比如均线周期调到 7 和 23 刚好在历史数据上表现最好,但换到实盘就失效。解决:参数优化时留一段样本外数据做验证,优化参数不要过于精细,均线周期用 5、10、20、30 这种整数,避免用 7、13、23 这种「玄学」数字。参照文档不会告诉你这些,这是实盘踩坑踩出来的。
5. 从参照文档到实盘:TB 语言进阶用法与验证习惯
5.1 用 TB 的跨周期引用做多周期共振
TB 支持跨周期引用,可以在日线策略里引用周线或分钟线的数据。这个功能在写多周期共振策略时非常有用。比如日线均线金叉,同时周线均线也金叉,才开仓。跨周期引用的语法是在函数后面加#和周期标识,比如Average(Close, 5)#WEEK表示周线的 5 周期均线。
// 跨周期引用示例:日线+周线共振 Vars NumericSeries DailyMA; NumericSeries WeeklyMA; Begin DailyMA = Average(Close, 10); WeeklyMA = Average(Close, 10)#WEEK; // 引用周线均线 If (DailyMA > DailyMA[1] && WeeklyMA > WeeklyMA[1] && MarketPosition == 0) Then Begin Buy(1, Close); End End逻辑说明:#WEEK是周期标识,TB 还支持#MIN30、#MIN60、#DAY等。跨周期引用时要注意数据对齐问题,周线数据在日线上的映射方式参照文档有说明,建议先在小周期上测试确认。
5.2 用 TB 的报警和日志功能做策略监控
TB 支持在策略里写报警和日志,方便实盘监控。报警用Alert函数,日志用Log函数。这两个功能在参照文档里篇幅不多,但实盘时非常实用。
// 报警和日志示例 If (MarketPosition == 1 && Close < MyStopLoss) Then Begin Sell(1, Close); Alert("止损触发,价格:" + Text(Close)); // 弹出报警 Log("止损触发,价格:" + Text(Close)); // 写入日志文件 End参数说明:Alert会弹出提示框,Log会写入 TB 的日志文件。Text函数把数值转成字符串,方便拼接。实盘时建议把关键信号都加上日志,方便事后复盘。
5.3 验证策略的 3 个习惯:样本外测试、参数敏感性、模拟盘
写了这么多年策略,我最大的教训是:回测漂亮不代表实盘能赚钱。现在我每次写完策略,都会做三件事。第一,留一段样本外数据做测试,比如用 2018-2020 年数据优化参数,用 2021-2022 年数据验证,如果样本外表现和样本内差距太大,说明过拟合了。第二,做参数敏感性测试,把均线周期上下浮动 20%,如果策略表现剧烈变化,说明参数太脆弱。第三,上模拟盘跑至少一个月,模拟盘能暴露很多回测发现不了的问题,比如滑点、成交延迟、信号丢失。
参照文档能帮你解决语法问题,但策略能不能赚钱,靠的是这些验证习惯。希望帮到你。
本文还有配套的精品资源,点击获取