- 策略广场
- 网格改进版 (实战原版)
网格改进版 (实战原版)
Author:
ianzeng123, Date: 2023-10-08 10:12:49
Tags:
/*backtest
start: 2024-10-15 00:00:00
end: 2024-11-15 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}]
*/
var obj = $.NewPositionManager(); // 使用发明者量化交易类库
var band = []; // 定义全局变量 band
var pos_dir = '--'
var pos_amount = '--'
var pos_price = '--'
var pos_profit = '--'
var pos_margin = 0
var stopprofit = 0
var stoploss = 0
function bandCal(records){
var ma = TA.MA(records, maPeriod)[records.length - 1]
var std = talib.STDDEV(records, stdPeriod)[records.length - 1]
var array = [-1.96, -0.85, -0.53, 0.53, 0.85, 1.96];
// 获取网格区间分界线
var band = array.map(num => _N(ma + num * std, 2))
return band
}
function timeSel() {
var t = new Date(); // 获取当前时间对象
var hour = t.getHours(); // 获取当前小时:0~23
var minute = t.getMinutes(); // 获取当前分钟:0~59
var day = t.getDay();
var isYes = false;
var minuteStr = minute.toString();
if (minuteStr.length === 1) {
minuteStr = "0" + minuteStr;
}
curtime = parseInt(hour.toString() + minuteStr, 10);
if ((day >= 1 && day <= 5) && // Monday to Friday
(curtime >= 900 && curtime <= 1130) || // 9:00 to 11:30 AM
(curtime >= 1330 && curtime <= 1500) || // 1:30 to 3:00 PM
(curtime >= 2100 && curtime <= 2300)) { // 21:00 to 23:00 PM
isYes = true;
}
return isYes
}
function onTick(records, mainId) {
// 此处用来获取持仓信息
var positions = _C(exchange.GetPosition) // 获取持仓数组
var position_amount = 0
for (var i = 0; i < positions.length; i++) { // 遍历持仓数组
if (positions[i]['Type'] === PD_LONG || positions[i]['Type'] === PD_LONG_YD) {
position_amount = 1 * positions[i].Amount // 将position_long标记为正数
} else if (positions[i]['Type'] === PD_SHORT || positions[i]['Type'] === PD_SHORT_YD) {
position_amount = -1 * positions[i].Amount // 将position_short标记为负数
}
}
// 根据价格落在(-inf,-1.96],(-1.96,-0.85],(-0.85,-0.53],(-0.53,0.53],(0.53,0.85], (0.85,1.96], (1.96, Inf) 的区间范围来获取最新收盘价所在的价格区间
var grid = null
var close_01 = records[records.length - 1].Close;
if (close_01 > band[5]) {
grid = 6
} else if (close_01 > band[4]) {
grid = 5
} else if (close_01 > band[3]) {
grid = 4
} else if (close_01 > band[2]) {
grid = 3
} else if (close_01 > band[1]) {
grid = 2
} else if (close_01 > band[0]) {
grid = 1
} else {
grid = 0
}
Log('当前网格区间:', grid)
// 若无仓位且价格突破则按照设置好的区间开仓
if (!position_amount) {
if (grid == 6 || grid == 0) {
band = bandCal(records) // 重新计算band
_G('band', band)
return('更新band')
}
if (grid > 3) {
obj.OpenShort(mainId, 1); // 以市价单开空仓到仓位
Log('空仓grid', grid)
}
if (grid < 3) {
obj.OpenLong(mainId, 1); // 以市价单开多仓到仓位
Log('多仓grid', grid)
}
}
// 持有空仓的处理
if (position_amount < 0) {
// 突破区间,进行止损,重新计算band
if (grid == 6) {
Log('止损平仓grid', grid)
obj.CoverAll(mainId) // 以市价单全平空仓
band = bandCal(records) // 重新计算band
stoploss += 1
}
// 等于3为在中间网格,平仓
else if (grid <= 3) {
Log('止盈平仓grid', grid)
obj.CoverAll(mainId) // 以市价单全平空仓
band = bandCal(records) // 重新计算band
stopprofit += 1
}
// 大于3为在中间网格的下方,加仓
else if (grid > 3 && -position_amount < maxPos) {
obj.OpenShort(mainId, 1) // 以市价单调空仓到仓位
}
}
// 持有多仓的处理
if (position_amount > 0) {
// 突破区间,进行止损,重新计算band
if (grid == 0) {
Log('止损平仓grid', grid)
obj.CoverAll(mainId) // 以市价单全平多仓
band = bandCal(records) // 重新计算band
stoploss += 1
}
// 等于3为在中间网格,平仓
else if (grid >= 3) {
Log('止盈平仓grid', grid)
obj.CoverAll(mainId) // 以市价单全平空仓
band = bandCal(records) // 重新计算band
stopprofit += 1
}
// 小于3为在中间网格的下方,加仓
else if (grid < 3 && position_amount < maxPos) {
obj.OpenLong(mainId, 1) // 以市价单调多仓到仓位
}
}
_G('band', band)
}
function main() {
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused|(CTP_T@10010)")
var preBartime = 0
var initAccount = _C(exchange.GetAccount)
// 获取主力合约
if(exchange.IO("status")){
var mainInfo = exchange.SetContractType(symbolID);
var mainId = mainInfo.InstrumentID;
}
// 读取保存网格数据;
band = _G('band')
// 保存网格数据为空;
if (band == null) {
Log('无存储网格数据')
_C(exchange.SetContractType, mainId)
records = _C(exchange.GetRecords)
if(records.length < 20) return
band = bandCal(records)
Log(band)
_G('band', band)
Log('已储存新的网格数据')
}else{
Log('载入已保存的网格数据')
}
while (true) { // 进入循环模式
if(exchange.IO("status") && timeSel()){
LogStatus("行情和交易服务器连接成功, " + _D())
// 订阅合约
var mainInfo = exchange.SetContractType(symbolID);
var mainId = mainInfo.InstrumentID;
exchange.SetContractType(mainId)
var records = _C(exchange.GetRecords)
if(preBartime != records[records.length - 1].Time){
preBartime = records[records.length - 1].Time
onTick(records, mainId)
}
var tblStatus = {
type: "table",
title: "持仓信息",
cols: ["合约名称", "持仓方向", "持仓均价", "持仓数量", "持仓盈亏", "止盈次数", "止损次数"],
rows: []
}
var statusPos = _C(exchange.GetPosition) // 获取持仓数组
if(statusPos.length != 0){
pos_dir = statusPos[0]['Type'] % 2 == 0 ? '多头' : '空头'
pos_amount = statusPos[0]['Amount']
pos_price = statusPos[0]['Price']
pos_profit = statusPos[0]['Profit']
pos_margin = statusPos[0].Margin
}else{
pos_dir = '--'
pos_amount = '--'
pos_price = '--'
pos_profit = '--'
pos_margin = 0
}
tblStatus.rows.push([mainId, pos_dir, pos_price, pos_amount, pos_profit, stopprofit, stoploss])
lastStatus = '`' + JSON.stringify([tblStatus]) + '`'
LogStatus(lastStatus)
var accountInfo = _C(exchange.GetAccount)
var curprofit = accountInfo.Info.Balance - initAccount.Info.Balance
LogProfit(curprofit, "权益", '&')
}else{
LogStatus("正在等待与交易服务器连接, " + _D())
}
Sleep(3000)
}
}
更多内容