- 金币:
-
- 奖励:
-
- 热心:
-
- 注册时间:
- 2016-5-17
|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
### CTP商品期货多品种海龟交易策略 (注释版)
--------------------------------------------------------------------
代码逐行翻译了一边,适合量化程序化初学者。
##### 听说看注释前, 熟悉一下海龟交易法,效果会更好哦!
```
/*
参数:
Instruments 合约列表 字符串(string) MA701,CF701,zn1701,SR701,pp1701,l1701,hc1610,ni1701,i1701,v1701,rb1610,jm1701,ag1612,al1701,jd1701,cs1701,p1701
LoopInterval 轮询周期(秒) 数字型(number) 3
RiskRatio % Risk Per N ( 0 - 100) 数字型(number) 1
ATRLength ATR计算周期 数字型(number) 20
EnterPeriodA 系统一入市周期 数字型(number) 20
LeavePeriodA 系统一离市周期 数字型(number) 10
EnterPeriodB 系统二入市周期 数字型(number) 55
LeavePeriodB 系统二离市周期 数字型(number) 20
UseEnterFilter 使用入市过滤 布尔型(true/false) true
IncSpace 加仓间隔(N的倍数) 数字型(number) 0.5
StopLossRatio 止损系数(N的倍数) 数字型(number) 2
MaxLots 单品种加仓次数 数字型(number) 4
RMode 进度恢复模式 下拉框(selected) 自动|手动
VMStatus@RMode==1 手动恢复字符串 字符串(string) {}
WXPush 推送交易信息 布尔型(true/false) true
MaxTaskRetry 开仓最多重试次数 数字型(number) 5
KeepRatio 预留保证金比例 数字型(number) 10
*/
var _bot = $.NewPositionManager(); // 调用CTP商品期货交易类库 的导出函数 生成一个用于单个品种交易的对象
// 源码模块地址 : 百度 BotVS
var TTManager = { // 海龟策略 控制器
New: function(needRestore, symbol, keepBalance, riskRatio, atrLen, enterPeriodA, leavePeriodA, enterPeriodB, leavePeriodB, useFilter,
multiplierN, multiplierS, maxLots) {
// 该控制器对象 TTManager 的属性 New 赋值一个 匿名函数(构造海龟的函数,即:构造函数),用于创建 海龟任务,参数分别是:
// needRestore: 是否需要恢复,symbol:合约代码,keepBalance:必要的预留的资金,riskRatio:风险系数, atrLen:ATR指标(参数)周期。enterPeriodA:入市周期A
// leavePeriodA:离市周期A , enterPeriodB:入市周期B, leavePeriodB:离市周期B,useFilter:使用过滤,multiplierN:加仓系数,multiplierS:止损系数,maxLots:最大加仓次数
// subscribe
var symbolDetail = _C(exchange.SetContractType, symbol);
// 声明一个局部变量 symbolDetail 用于接受API SetContractType 函数的返回值(值为symbol的合约的详细信息,symbol 是 "MA709",返回的就是甲醇709合约的详细信息),
// 调用API SetContractType 订阅并切换合约为 symbol 变量值的合约。 _C() 函数的作用是 对 SetContractType 合约容错处理,即如果 SetContractType返回null 会循环重试。
if (symbolDetail.VolumeMultiple == 0 || symbolDetail.MaxLimitOrderVolume == 0 || symbolDetail.MinLimitOrderVolume == 0 || symbolDetail.LongMarginRatio == 0 || symbolDetail.ShortMarginRatio == 0) {
// 如果 返回的合约信息对象symbolDetail 中 VolumeMultiple、MaxLimitOrderVolume 等数据异常,则调用 throw 抛出错误,终止程序。
Log(symbolDetail);
throw "合约信息异常";
} else { // 检索的数据没有异常则,输出部分合约信息。
Log("合约", symbolDetail.InstrumentName, "一手", symbolDetail.VolumeMultiple, "份, 最大下单量", symbolDetail.MaxLimitOrderVolume, "保证金率:", _N(symbolDetail.LongMarginRatio), _N(symbolDetail.ShortMarginRatio), "交割日期", symbolDetail.StartDelivDate);
}
var ACT_IDLE = 0; // 定义一些宏 (标记)
var ACT_LONG = 1;
var ACT_SHORT = 2;
var ACT_COVER = 3; // 动作宏
var ERR_SUCCESS = 0; // 错误宏
var ERR_SET_SYMBOL = 1;
var ERR_GET_ORDERS = 2;
var ERR_GET_POS = 3;
var ERR_TRADE = 4;
var ERR_GET_DEPTH = 5;
var ERR_NOT_TRADING = 6;
var errMsg = ["成功", "切换合约失败", "获取订单失败", "获取持仓失败", "交易下单失败", "获取深度失败", "不在交易时间"]; // 错误宏的值 对应该数组的索引,对应索引的值就是翻译
var obj = { // 声明一个对象,构造完成后返回。单个的海龟策略控制对象。
symbol: symbol, // 合约代码 构造函数执行时的参数传入
keepBalance: keepBalance, // 预留的资金 构造函数执行时的参数传入
riskRatio: riskRatio, // 风险系数 构造函数执行时的参数传入
atrLen: atrLen, // ATR 长度 构造函数执行时的参数传入
enterPeriodA: enterPeriodA, // 入市周期A 构造函数执行时的参数传入
leavePeriodA: leavePeriodA, // 离市周期A 构造函数执行时的参数传入
enterPeriodB: enterPeriodB, // 入市周期B 构造函数执行时的参数传入
leavePeriodB: leavePeriodB, // 离市周期B 构造函数执行时的参数传入
useFilter: useFilter, // 使用入市过滤条件 构造函数执行时的参数传入
multiplierN: multiplierN, // 加仓系数 基于N 构造函数执行时的参数传入
multiplierS: multiplierS // 止损系数 基于N 构造函数执行时的参数传入
};
obj.task = { // 给 obj对象添加一个 task 属性(值也是一个对象),用来保存 海龟的任务状态数据。
action: ACT_IDLE, // 执行动作
amount: 0, // 操作量
dealAmount: 0, // 已经处理的操作量
avgPrice: 0, // 成交均价
preCost: 0, // 前一次交易成交的额度
preAmount: 0, // 前一次成交的量
init: false, // 是否初始化
retry: 0, // 重试次数
desc: "空闲", // 描述信息
onFinish: null // 处理完成时的 回调函数,即可以自行设定一个 回调函数在完成当前 action 记录的任务后执行的代码。
}
obj.maxLots = maxLots; // 赋值 最大加仓次数 构造函数执行时的参数传入
obj.lastPrice = 0; // 最近成交价,用于计算 持仓盈亏。
obj.symbolDetail = symbolDetail; // 储存 合约的详细信息 到obj 对象的 symbolDetail 属性
obj.status = { // 状态数据
symbol: symbol, // 合约代码
recordsLen: 0, // K线长度
vm: [], // 持仓状态 , 用来储存 每个品种的 ,手动恢复字符串。
open: 0, // 开仓次数
cover: 0, // 平仓次数
st: 0, // 止损平仓次数
marketPosition: 0, // 加仓次数
lastPrice: 0, // 最近成交价价格
holdPrice: 0, // 持仓均价
holdAmount: 0, // 持仓数量
holdProfit: 0, // 浮动持仓盈亏
N: 0, // N值 , 即ATR
upLine: 0, // 上线
downLine: 0, // 下线
symbolDetail: symbolDetail, // 合约详细信息
lastErr: "", // 上次错误
lastErrTime: "", // 上次错误时间信息
stopPrice: '', // 止损价格
leavePrice: '', //
isTrading: false // 是否在交易时间
};
obj.setLastError = function(err) { // 给obj对象添加方法,设置 最近一次的错误信息
if (typeof(err) === 'undefined' || err === '') { // 如果参数未传入,或者 错误信息为 空字符串
obj.status.lastErr = ""; // 清空 obj 对象的 status 属性的 对象的lastErr属性
obj.status.lastErrTime = ""; // 清空
return; // 返回
}
var t = new Date(); // 获取新时间
obj.status.lastErr = err; // 设置错误信息
obj.status.lastErrTime = t.toLocaleString(); // toLocaleString() 根据本地时间格式,把 Date 对象转换为字符串。
};
obj.reset = function(marketPosition, openPrice, N, leavePeriod, preBreakoutFailure) { // 给obj对象添加方法,恢复仓位。
// 参数,marketPosition:加仓次数,openPrice:最后一次加仓价, N:N值, leavePeriod:离市周期,preBreakoutFailure:是否上次突破失败
if (typeof(marketPosition) !== 'undefined') { // 如果 第一个参数不是未定义 ,传入参数
obj.marketPosition = marketPosition; // 给obj 添加属性 marketPosition : 加仓次数 正数为多仓,负数为空仓
obj.openPrice = openPrice; // 最后一次加仓价
obj.preBreakoutFailure = preBreakoutFailure; // 是否上次突破失败
obj.N = N; // N值
obj.leavePeriod = leavePeriod; // 离市周期
var pos = _bot.GetPosition(obj.symbol, marketPosition > 0 ? PD_LONG : PD_SHORT); // 调用 模板类库生成的 交易控制对象的成员函数GetPosition 获取 持仓信息
if (pos) { // 如果获取到持仓信息
obj.holdPrice = pos.Price; // 根据获取的持仓信息 给obj 属性赋值
obj.holdAmount = pos.Amount; // 同上
Log(obj.symbol, "仓位", pos); // 输出显示当前仓位
} else { // 如果GetPosition 返回null ,没有找到持仓信息。
throw "恢复" + obj.symbol + "的持仓状态出错, 没有找到仓位信息"; // 抛出异常
}
Log("恢复", obj.symbol, "加仓次数", obj.marketPosition, "持仓均价:", obj.holdPrice, "持仓数量:", obj.holdAmount, "最后一次加仓价", obj.openPrice, "N值", obj.N, "离市周期:", leavePeriod, "上次突破:", obj.preBreakoutFailure ? "失败" : "成功");
// 输出恢复的 相关参数,数据。
obj.status.open = 1; // 设置 开仓 计数为1
obj.status.vm = [obj.marketPosition, obj.openPrice, obj.N, obj.leavePeriod, obj.preBreakoutFailure]; // 储存 手动恢复字符串 数据。
} else { // 没有传入参数,即不恢复, 全部初始化。
obj.marketPosition = 0; // 初始化各项变量
obj.holdPrice = 0;
obj.openPrice = 0;
obj.holdAmount = 0;
obj.holdProfit = 0;
obj.preBreakoutFailure = true; // test system A // 此处设置true 会使策略 尝试 突破系统A
obj.N = 0;
obj.leavePeriod = leavePeriodA; // 用系统A 的离市周期 赋值
}
obj.holdProfit = 0; // 初始化
obj.lastErr = "";
obj.lastErrTime = "";
};
obj.Status = function() { // 给Obj 添加 Status 函数, 把Obj 的一些属性值 赋值给 Obj.status 同样意义的属性
obj.status.N = obj.N; // 给 obj.status 赋值
obj.status.marketPosition = obj.marketPosition;
obj.status.holdPrice = obj.holdPrice;
obj.status.holdAmount = obj.holdAmount;
obj.status.lastPrice = obj.lastPrice;
if (obj.lastPrice > 0 && obj.holdAmount > 0 && obj.marketPosition !== 0) { // 如果有持仓
obj.status.holdProfit = _N((obj.lastPrice - obj.holdPrice) * obj.holdAmount * symbolDetail.VolumeMultiple, 4) * (obj.marketPosition > 0 ? 1 : -1);
// 计算持仓盈亏 = (最近成交价 - 持仓价格)* 持仓量 * 一手合约份数 , 计算出来 保留4位小数, 用 obj.marketPosition(加仓次数) 属性的 正负 去修正,计算结果的正负(做空按照这个算法是相反的负数,所以要用-1修正)。
} else {
// 如果没有持仓,浮动盈亏赋值为0
obj.status.holdProfit = 0;
}
return obj.status; // 返回这个 obj.status 对象(用于显示在界面状态栏?)
};
obj.setTask = function(action, amount, onFinish) { // 给obj 对象添加 方法,设置任务
// 参数,action:执行动作,amount:数量,onFinish: 回调函数
obj.task.init = false; // 重置 初次执行标记 为false
obj.task.retry = 0; // 重置..
obj.task.action = action; // 参数传来的 动作指令 赋值
obj.task.preAmount = 0; // 重置
obj.task.preCost = 0;
obj.task.amount = typeof(amount) === 'number' ? amount : 0; // 如果没传入参数 ,设置 0
obj.task.onFinish = onFinish;
if (action == ACT_IDLE) { // 如果 动作指令是 空闲
obj.task.desc = "空闲"; // 描述变量 赋值为 “空闲”
obj.task.onFinish = null; // 赋值为 null
} else { // 其他动作
if (action !== ACT_COVER) { // 如果不等于 平仓动作
obj.task.desc = (action == ACT_LONG ? "加多仓" : "加空仓") + "(" + amount + ")"; // 根据 action 设置描述 信息
} else { // 如果是平仓 动作 设置描述信息为 “平仓”
obj.task.desc = "平仓";
}
Log("接收到任务", obj.symbol, obj.task.desc); // 输出日志 显示 接收到任务。
// process immediately
obj.Poll(true); // 调用 obj 对象的方法 处理 任务,参数是 true , 参数为true ,控制Poll 只执行 一部分(子过程)
}
};
|
|
|