Dual Thrust 商品期货 (注释版)

  • 基本原理

在当天收盘,计算两个值: 最高价-收盘价,和收盘价-最低价。然后取这两个值较大的那个,乘以k值,结果称为触发值。
在第二天开盘,记录开盘价,然后在价格超过(开盘+触发值)时马上买入,或者价格低于(开盘-触发值)时马上卖空。
这个系统是反转系统,没有单独止损。也就是说,反向信号也同时就是平仓信号。

  • 图解

    Dual Thrust 策略包含完整的图表显示, 图表动态更新,模板引用等功能, 可做学习模板使用.

    策略的详细介绍 : http://xueqiu.com/5256769224/32429363

  • 注释版 源码:

/* 引用的类库《商品期货交易类库》   引用了这个 模板,具体模板代码 可以在 策略广场 找到,也有注释版的(注释版在论坛,即 交流社区)
*//* 参数名称(全局变量) 中文含义              数据类型            值
ContractTypeName    合约品种              字符串(string)      MA701
NPeriod             计算周期              数字型(number)      4
Ks                  上轨系数              数字型(number)      0.5
Kx                  下轨系数              数字型(number)      0.5
AmountOP            开仓合约张数           数字型(number)      1
Interval            重试间隔(毫秒)         数字型(number)      2000
LoopInterval        轮询间隔(秒)           数字型(number)      3
PeriodShow          图表最大显示K线柱数     数字型(number)      500
NotifyWX            下单微信通知           布尔型(true/false)  true
CoverAll            启动策略时清空合约仓位   布尔型(true/false)  false
*/var ChartCfg = {                          // ChartCfg 是一个  全局 JS 对象, 用来 初始化 策略图表 设置。 对象有很多关于图表功能的属性。   图表库为:HighCharts__isStock: true,                      // 该属性用于 控制 是否显示为 单独控制 数据序列(可以在图表上取消单独一个 数据序列的显示),如果指定__isStock: false, 则显示为普通图表title: {                              // title : 图表的主要 标题text: 'Dual Thrust 上下轨图'       //  title 的一个属性 text : 标题的 文本, 这里  设置为 'Dual Thrust 上下轨图' 该文本就会显示在标题位置},yAxis: {                              // 图表 坐标Y轴的 相关设置plotLines: [{                     // Y轴上的 水平线  (和Y轴垂直)  ,该属性的值是一个数组,即 多条水平线的设置value: 0,                     // 水平线 在Y轴上的坐标值color: 'red',                 // 水平线的颜色width: 2,                     // 水平线的 线宽label: {                      // 水平线 上的 标签text: '上轨',              // 标签的 文本align: 'center'           // 标签 的显示位置,这里设置 为 居中(即 :'center')},}, {                              // 第二条 水平线   ( [{...},{...}]  数组中的第二个 元素)value: 0,                     // 水平线 在Y轴上的坐标值color: 'green',               // 水平线的颜色width: 2,                     // 水平线的 线宽label: {                      // 标签text: '下轨',align: 'center'},}]},series: [{                            // 数据序列, 即用来 在图表上显示 数据线 、K线、标记 等等 内容的 数据。 也是一个数组 第一个 索引为 0 。type: 'candlestick',              // 索引为0 数据序列的 类型:  'candlestick' 表示为 K线图name: '当前周期',                  //  数据序列的 名称id: 'primary',                    //  数据序列的ID   ,用于 下一个数据序列相关设置。data: []                          //  数据序列的 数组, 用于储存具体的 K线数据}, {type: 'flags',                    // 数据序列 ,类型 : 'flags',在图表上显示 标签,表示 做多  和   做空。 索引为 1 。onSeries: 'primary',              // 这个属性 表示 标签 显示在 id 为 'primary' 上。data: [],                         //  保存 标签数据的 数组。}]
};var STATE_IDLE = 0;                       // 状态常量, 表示 空闲
var STATE_LONG = 1;                       // 状态常量, 表示 持多仓
var STATE_SHORT = 2;                      // 状态常量, 表示 持空仓
var State = STATE_IDLE;                   // 表示当前程序状态 ,初始 赋值为空闲var LastBarTime = 0;                      // K线最后一柱的时间戳(单位为 毫秒, 1000毫秒 等于 1秒, 时间戳是 1970年1月1日 到现在时刻的 毫秒数是一个很大的 正整数)
var UpTrack = 0;                          // 上轨 值
var BottomTrack = 0;                      // 下轨 值
var chart = null;                         // 用于接受   Chart 这个 API 函数返回的 图表控制对象。用该对象(chart) 可以调用其成员函数 向图表内写入数据。
var Counter = {                           // 计数器, 用于记录 盈亏次数w: 0,                                 // 赢次数l: 0                                  // 亏次数
};var manager = null;                       // 用于储存  商品期货交易类库  模板导出函数 返回的 交易对象。该对象用于下单交易逻辑处理
var logSuffix = NotifyWX ? '@' : '';      // 微信开关, 界面上的参数NotifyWX 如果为true , logSuffix 就被初始化 为 '@' , 在程序中Log的时候 就会推送绑定的微信// 具体可以参见Log 函数 这个API。function onTick(exchange) {               // 程序 主要函数,程序主要逻辑都是在该函数内处理。if (!manager) {                       // 判断 manager 是否初始化,如果 为null 即 没有初始化,则执行 if 模块 ( {..} 内 )。manager = $.NewPositionManager(); // 调用  商品期货交易类库 的导出函数 $.NewPositionManager , 该函数返回一个 用于控制具体下单交易的对象 给 manager。 if (_C(exchange.GetPosition).length > 0) {   //  调用 exchange.GetPosition 函数获取 当前持仓信息, _C 是容错函数,用来重试(即 返回null了就会重试)。//  exchange.GetPosition 函数 返回一个数组, 访问 这个返回值的 length 属性,如果大于0,即,返回的数组内有元素,代表当前有持仓。if (CoverAll) {                          //  如果 界面参数  CoverAll 被设置为 true  ,即:启动策略时清空合约仓位manager.Cover(ContractTypeName);     //  调用 商品期货交易类库 生成的 底层交易控制对象 manager 的成员函数Cover ,参数为 界面参数 上设置的合约代码,//  平掉所有合约为 ContractTypeName 的持仓, 回测时注意 该合约ContractTypeName是不是 在回测时间段内存在。Log("已清空所有相关仓位");              //  输出日志 提示信息} else {                                 //  CoverAll 被设置为false 则执行以下throw "策略启动前不能有持仓.";           //  抛出错误  “策略启动前不能有持仓”}}Log('交易平台:', exchange.GetName(), _C(exchange.GetAccount));    // 输出日志, 显示当前设定的交易所对象的名称(调用 exchange.GetName获取),显示当前// 交易所对象的账户信息(调用 exchange.GetAccount获取)var insDetail = _C(exchange.SetContractType, ContractTypeName);  // 获取 ContractTypeName 合约的 详细信息 ,并订阅切换为ContractTypeName合约。 Log("合约", insDetail.InstrumentName, "一手", insDetail.VolumeMultiple, "份, 最大下单量", insDetail.MaxLimitOrderVolume, "保证金率:", insDetail.LongMarginRatio.toFixed(4), insDetail.ShortMarginRatio.toFixed(4), "交割日期", insDetail.StartDelivDate);// 输出ContractTypeName 合约的详细信息。}var records = _C(exchange.GetRecords);                               // 调用 exchange.GetRecords 函数 获取K线数据if (!records || records.length <= NPeriod) {                         // 如果 records 为 null  或者 records 数组长度 小于等于 界面参数 NPeriod (计算周期)执行if 块内代码LogStatus("Calc Bars...");                                       // 调用 LogStatus 在状态栏 输出 提示信息 :  意思为 正在收集K线数据return;                                                          // 返回 即 onTick 函数本次运行结束。用此处 判断确保 K线数量足够(超过 设置的 NPeriod 参数)}var Bar = records[records.length - 1];                               // 当K线长度条件符合执行到此时, 取K线数据 records 的最后一个数据(即倒数第一根K线柱)if (LastBarTime !== Bar.Time) {                                      // 全局变量LastBarTime 记录的时间戳 如果不等于当前的K线数据最后一个Bar的时间戳,即 :当前的K线数据最后一个Bar 是更新的(新出现的Bar)。var HH = TA.Highest(records, NPeriod, 'High');                   // 声明HH 变量 ,调用 TA.Highest 函数计算 当前K线数据 NPeriod 周期内最高价 的最大值 赋值给HH。var HC = TA.Highest(records, NPeriod, 'Close');                  // 声明HC 变量 ,获取 NPeriod 周期内的 收盘价的最大值。var LL = TA.Lowest(records, NPeriod, 'Low');                     // 声明LL 变量 ,获取 NPeriod 周期内的 最低价的最小值。var LC = TA.Lowest(records, NPeriod, 'Close');                   // 声明LC 变量 ,获取 NPeriod 周期内的 收盘价的最小值。  具体 TA 指标API 参见平台API 指标页面。var Range = Math.max(HH - LC, HC - LL);                          // 计算出 范围UpTrack = _N(Bar.Open + (Ks * Range));                           // 根据 界面参数的 上轨系数 Ks  最新K线柱的 开盘价 等,计算出 上轨值。DownTrack = _N(Bar.Open - (Kx * Range));                         // 计算下轨值if (LastBarTime > 0) {                                           // 由于LastBarTime 该变量初始化设置的 值为 0 ,所以第一次运行到此处 LastBarTime > 0 必定是 false ,不会执行if 块内的代码,而是会执行else 块内的代码var PreBar = records[records.length - 2];                    // 声明一个变量 含义是 “前一个Bar” 把当前K线的 倒数第二Bar 赋值给它。chart.add(0, [PreBar.Time, PreBar.Open, PreBar.High, PreBar.Low, PreBar.Close], -1);  // 调用 chart 图标控制对象的 add函数 更新K线数据(用获取的K线数据的倒数第二Bar 去更新 图标的倒数第一个Bar,因为有新的K线Bar 生成)// chart.add 函数的具体用法 参见API 文档,和论坛里的文章。} else {                                                                                  // 程序第一次运行到此 必定执行 else 块内代码,主要作用是 把第一次获取的K线一次性全部添加到图表上。for (var i = Math.min(records.length, NPeriod * 3); i > 1; i--) {                     // 此处执行一个 for 循环, 循环次数 使用 K线长度和NPeriod 3倍 二者中最小的值,可以保证初始的K线不会画的太多太长。索引是从大到小的。var b = records[records.length - i];                                              // 声明一个 临时 变量b 用来取每次循环 索引为 records.length - i 的K线柱 数据。chart.add(0, [b.Time, b.Open, b.High, b.Low, b.Close]);                           // 调用 chart.add 函数 向图表添加K线柱,注意 add函数最后一个参数如果传入-1 就是更新图表上最后一个Bar(柱),如果没传参数,就是向最后添加Bar// 执行完 i 等于 2 这次循环后(i-- 了已经,此时为1了),就会触发 i > 1 为false 停止循环, 可见 此处代码只处理到 records.length - 2 这个Bar// 最后一个Bar 没有处理。}}chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close]);                         // 由于以上 if 的2个分支 都没处理 records.length - 1这个Bar,所以 此处 处理。添加最新出现的Bar 到图表中。ChartCfg.yAxis.plotLines[0].value = UpTrack;                                              // 把计算出来的 上轨值 赋值给 图表对象(区别于 图表控制对象chart),用于稍后显示。ChartCfg.yAxis.plotLines[1].value = DownTrack;                                            // 赋值下轨值ChartCfg.subtitle = {                                                                     // 设置副标题 text: '上轨: ' + UpTrack + '  下轨: ' + DownTrack                                      // 副标题文本 设置 ,在副标题上显示出  上轨 下轨 值。};chart.update(ChartCfg);                                                                   // 用图表对象 ChartCfg 更新图表chart.reset(PeriodShow);                                                                  // 刷新 根据界面参数 设置的 PeriodShow 变量 ,只保留PeriodShow 的值数量的 K线柱。LastBarTime = Bar.Time;                                                                   // 此次新产生的 Bar 的时间戳 更新给 LastBarTime 用于判断 下次循环 获取的K线数据最后一个Bar 是否是新产生的。} else {                                                                                      // 如果 LastBarTime 等于 Bar.Time 即: 没有新的K线Bar 产生。 则执行一下  {..} 内代码chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close], -1);                     // 用当前K线数据的最后一个Bar(K线的最后一个Bar 即当前周期的Bar是不断在变化的),更新图表上的最后一个K线柱。}LogStatus("Price:", Bar.Close, "Up:", UpTrack, "Down:", DownTrack, "Wins: ", Counter.w, "Losses:", Counter.l, "Date:", new Date());  // 调用LogStatus 函数显示 当前策略的数据在状态栏上。var msg;                                                                                                                             // 定义一个 变量msg 意义是 消息。if (State === STATE_IDLE || State === STATE_SHORT) {                                          // 判断 当前状态变量 State 是否等于 空闲  或者 State 是否等于 持空仓, 在空闲状态下可以触发做多, 在持空仓状态下可以触发 平多仓,并反手。if (Bar.Close >= UpTrack) {                                                               // 如果当前K线的 收盘价 大于 上轨值 ,执行 if 块内代码。msg  = '做多 触发价: ' + Bar.Close + ' 上轨:' + UpTrack;                                // 给 msg 赋值 ,把需要显示的 数值 组合成字符串。if (State !== STATE_IDLE) {                                                           // 如果 当前状态不为空闲(只有空闲和持空仓可以进入此处代码,若不为空闲,必定是持空仓),所以以下{..}内 处理 平空仓工作。manager.Cover(ContractTypeName);                                                  // 调用 manager 的 Cover 函数 参数传入 ContractTypeName 确定平仓 品种。执行 平仓具体操作。var profit = manager.Profit();                                                    // 声明 profit 变量 储存 manager 对象的成员函数 Profit 函数返回的 收益值。(Profit函数用于计算收益。)LogProfit(profit);                                                                // 调用LogProfit 输出收益并打印收益曲线, 此函数 可详见API文档。msg += ' 平仓利润: ' + profit;                                                     // 在msg 消息字符串后 添加收益信息。}Log(msg + logSuffix);                                                                 // 输出 日志信息, 会根据logSuffix 的值(是否是 "@")进行微信同步消息推送, "@"的作用具体参见 API文档 中的Log 函数。manager.OpenLong(ContractTypeName, AmountOP);                                         // 开多 或 反手 :   调用manager 对象的OpenLong 根据界面参数AmountOP设置的手数下单开多仓。State = STATE_LONG;                                                                   // 无论 开多仓 还是 反手 ,此刻程序状态 要更新为 持多仓。chart.add(1, {x:Bar.Time, color: 'red', shape: 'flag', title: '多', text: msg});       // 在K线相应的位置 添加一个 标记  显示 开多。 }}if (State === STATE_IDLE || State === STATE_LONG) {                                           // 做空方向 与 以上 同理,不在赘述。代码完全一致。if (Bar.Close <= DownTrack) {msg = '做空 触发价: ' + Bar.Close + ' 下轨:' + DownTrack;if (State !== STATE_IDLE) {manager.Cover(ContractTypeName);var profit = manager.Profit();LogProfit(profit);msg += ' 平仓利润: ' + profit;}Log(msg + logSuffix);manager.OpenShort(ContractTypeName, AmountOP);chart.add(1, {x:Bar.Time, color: 'green', shape: 'circlepin', title: '空', text: msg});State = STATE_SHORT;}}
}function onexit() {                                                                               // 扫尾函数,停止 程序时会触发该函数执行。var pos = _C(exchange.GetPosition);                                                           // 获取持仓信息。if (pos.length > 0) {                                                                         // 如果有持仓信息Log("警告, 退出时有持仓", pos);                                                              // 输出 日志 提示。}
}function main() {                                                                                 //  策略程序的 主函数。(入口函数)if (exchange.GetName() !== 'Futures_CTP') {                                                   //  判断添加的交易所对象 的名称(通过exchange.GetName函数获取) 如果不等于 'Futures_CTP' 即:添加的不是传统期货交易所对象。throw "只支持传统商品期货(CTP)";                                                             //  抛出异常 }SetErrorFilter("login|ready");                                                                //  设置错误过滤LogStatus("Ready...");                                                                        //  状态栏显示 “准备..”文本LogProfitReset();                                                                             //  清空之前的收益日志chart = Chart(ChartCfg);                                                                      //  调用API  Chart 函数, 用图表对象ChartCfg初始化,返回 图表控制对象。 chart.reset();                                                                                //  调用图表控制对象的成员函数 reset 清空所有图表上的 数据(数据序列的内容)LoopInterval = Math.max(LoopInterval, 1);                                                     //  设定循环 时间,最小 不小于1.while (true) {                                                                                //  主要循环if (exchange.IO("status") && $.IsTrading(ContractTypeName)) {                             //  必须确保 与交易所服务器 连接的状态下(exchange.IO("status") 返回true 就是链接上了) 并且 在该品种(ContractTypeName)的交易时间内 (通过IsTrading函数判断) 才可执行 onTick 函数onTick(exchange);                                                                     //  执行 onTick 函数,即: 策略主要逻辑} else {                                                                                  //  exchange.IO("status") 返回 false 即: 未连接LogStatus("未登录状态或不在交易时间段内");                                                 //  在状态栏 显示 提示信息。}Sleep(LoopInterval * 1000);                                                               //  根据参数 LoopInterval 轮训等待, 避免程序访问 交易所 API 过于频繁导致 问题。}
}

Dual Thrust 商品期货 (注释版)相关推荐

  1. 商品期货套利 - 多品种网格对冲模型 注释版

    商品期货套利 - 多品种网格对冲模型 注释版 #### 代码: // 商品期货套利 - 多品种网格对冲模型 注释版 function Hedge(q, e, positions, symbolA, s ...

  2. 商品期货策略 之 Python 精简多品种 MACD 趋势策略框架(注释版)

    Python 精简多品种 MACD 趋势策略框架(注释版) Python超级精简的多品种MACD趋势策略框架, 代码超级精简, 注释超级详细啰嗦. >_<! 需要引用 python版CTP ...

  3. python量化外汇交易_用Python实现一个Dual Thrust数字货币量化交易策略

    Dual Thrust交易算法介绍 Dual Thrust交易算法是由Michael Chalek开发的著名量化交易策略.它通常用于期货,外汇和股票市场.Dual Thrust的概念属于典型的突破交易 ...

  4. python 用while输出数字金字塔_用Python实现一个Dual Thrust数字货币量化交易策略

    Dual Thrust交易算法介绍 Dual Thrust交易算法是由Michael Chalek开发的著名量化交易策略.它通常用于期货,外汇和股票市场.Dual Thrust的概念属于典型的突破交易 ...

  5. html5连连看源码解析,JS连连看源码完美注释版(推荐)

    JS连连看源码完美注释版 table{ border-collapse: collapse; } td{ border: solid #ccc 1px; height: 36px; width: 36 ...

  6. WinAPI入门: 第一个标准Win32窗口程序 [改进详细注释版]

    WinAPI入门: 第一个标准Win32窗口程序 下载链接: 若想立即看到本程序的运行结果,可点击EXE文件的免费下载链接; HelloWin_v1.sfx.exe;–带语音和背景音乐; 相关链接: ...

  7. 手撕Resnet卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑。跑的代码有问题的可以在评论区指出,看到了会回复。训练代码和预测代码均有。

    Alexnet网络详解代码:手撕Alexnet卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑.跑的代码有问题的可以在评论区指出,看到了会回复.训练代 ...

  8. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 下

    文章目录 1 测试鉴别器 2 建立生成器 3 测试生成器 4 训练生成器 5 使用生成器 6 内存查看 上一节,我们已经建立好了模型所必需的鉴别器类与Dataset类. 使用PyTorch构建GAN生 ...

  9. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 上

    文章目录 1 数据集描述 2 GPU设置 3 设置Dataset类 4 设置辨别器类 5 辅助函数与辅助类 1 数据集描述 此项目使用的是著名的celebA(CelebFaces Attribute) ...

  10. 爱丽丝漫游奇景注释版拿到手了

    今天拿到了爱丽丝漫游奇景的注释版. 书是绝书,长盛不衰100多年,成人小孩都能读得兴味盎然:人是妙人,作者Lewis Carrol和注者Martin Gardner都有生花妙笔,深厚学养.数学和逻辑由 ...

最新文章

  1. 面试中多说这么一句话,薪水直接涨5k
  2. iOS截取NSString字符串
  3. [20170606]11G _optimizer_null_aware_antijoin.txt
  4. HTTP Strict Transport Security (HSTS) in ASP.NET Core
  5. android 旋转生命周期,生命周期-如何区分方向更改和离开应用程序android
  6. Spring之AOP面向切面编程
  7. PHP学习九--会话控制session和cookie
  8. 电商常用三大数据分析模型--深入浅出
  9. 新版代shua社区源码(云商城1.0)
  10. 微信域名防封最全代码
  11. WebService之CXF框架
  12. 计算机主机报警 声,电脑开机报警声音大全
  13. npx create-react-app 动不了???(解决方法)
  14. UI基本控件(一):UIScrollView
  15. java 远程文件操作_java远程文件操作 - osc_88djj30s的个人空间 - OSCHINA - 中文开源技术交流社区...
  16. android.265g.com.,小米3s流产?小米3下一代机型为小米x4?
  17. 外卖cps 赚钱小程序源码
  18. “全民来答题”用户协议
  19. 很抱歉,此功能看似已中断,并需要修复。请使用Windows控制面板中的“程序和功能”选项修复Microsoft Office。
  20. display:block含义

热门文章

  1. 运维工程师必须掌握的基础技能有哪些?
  2. 项目经理如何做好风险管理
  3. 华为u2000v200r018 同步网元失败 提示 服务器不可达 解决办法
  4. MBlock-scartch开发环境搭建
  5. 1.6秒能干什么?自动锁螺丝机表演给你看
  6. DSPTMS320C6678的数据导入方法
  7. AcWing 棋盘挑战 dsf
  8. Unity 安装失败原因
  9. 程序员自编的中华古诗词数据库在GitHub上火了!
  10. [Sql2008错误问题] 配置系统未能初始化 0x84B10001