上一篇我们实现了一个简单的均线策略,本期我们一起来看如何实现一个网格策略。股票网格策略比较简单,相对于可以做多做空的期货,股票就只能做多了。网格策略就只能向下挂买单,分散持仓价格位置,持续低吸。等待到价格反弹逐笔平仓或者全部平仓。
策略设计
策略同样可以使用我们之前使用的程序结构框架,需要做一些修改即可实现一个网格策略。设计策略时要用最简单的设计思路,尽量让程序逻辑简洁,这样便于维护、修改、扩展。考虑到同样可以让策略做多个股票,所以我们对于网格的每个点的差价设置成一个比例,这样我们设置一个参数即可,就不用设置一堆参数,给每个股票都设置具体的网格节点差价。
DiffPricePercent 网格节点差价
可以理解为开仓一次到下一次开仓时的价格差,参数是一个小数,例如设置0.02
即代表2%。表示当前价格减去当前价格的2%
得出的价格为下一次开仓的价格。对于网格的起始价格应该是可以指定的,所以我们设计了BeginPrices
参数。
BeginPrices
参数BeginPrices
设计成一个字符串,可以输入一个数组JSON字符串,让策略解析为一个数组结构,在策略初始化时给每只股票的数据结构分配一个网格初始价格。这个起始价格我们可能有时会指定,但是有时又想让以当前价格为起始价格,那怎么办?这个设计很简单,如果需要让以当前价格为初始价格我们就设置-1,代表当前价格。
// 更新行情数据
symbols[i].CurrPrice = ticker.Last
if (symbols[i].BeginPrice == -1) {
symbols[i].BeginPrice = ticker.Last
}
我们只用在策略中检测这个起始价格是不是-1,如果是-1,把当前价格赋值给这个变量记录即可。
这些是我们在程序框架基础上添加的2个参数。
策略图表也需要修改,我想要的是这样的效果....我的脑海里出现这样的画面:
那就动手实现吧。
图表设计
分析我们的需求,除了普通的K线图表显示以外,我们还需要绘制网格每个价格位置的水平线。所以我们需要根据当前的持仓、DiffPricePercent
参数、起始价格等数据去计算当前的网格。以下代码为计算每个网格的价格。
...
var hasPosAmount = posAmount
var beginPrice = symbols[i].BeginPrice
var count = 0
while (true) {
if (count == 0) { // 第一个点是起始点,给图表配置结构写入对应的数据
symbols[i].ChartCfg.yAxis.plotLines.push({ // symbols[i].ChartCfg 即当前股票的图表配置变量
value: beginPrice,
color: 'red',
width: 2,
label: {
text: '起始价格',
align: 'center'
},
})
count++
continue
}
beginPrice = beginPrice - beginPrice * DiffPricePercent // 计算得出当前节点的价格beginPrice
hasPosAmount = hasPosAmount - TradeAmount
symbols[i].ChartCfg.yAxis.plotLines.push({ // 写入图表配置
value: beginPrice,
color: 'blue',
width: 2,
label: {
text: '节点:' + count,
align: 'center'
},
})
if (hasPosAmount < 0) { // 检测到未开仓位置,跳出循环
_Chart.update(_ArrChart)
break
}
count++
}
策略交易逻辑
策略交易逻辑比较简单,只要当前价格低于计算出的最后一个网格节点价格,就买入。
如果当前价格高于持仓均价达到持仓均价的2 * DiffPricePercent
倍,就卖出。
if (ticker.Last < beginPrice) {
// 买入
Log(contractTypeName, "开多仓", "beginPrice:", beginPrice, "posAmount:", posAmount)
Buy(exchange, contractTypeName, TradeAmount, ticker.Info)
symbols[i].State = STATE_LONG
}
if (posAmount > 0 && pos.CanCoverAmount > 0 && ticker.Last > pos.Price + pos.Price * DiffPricePercent * 2) {
// 平仓
Log(contractTypeName, "平多仓")
Sell(exchange, contractTypeName, Math.min(pos.CanCoverAmount, posAmount), ticker.Info)
symbols[i].State = STATE_IDLE
}
策略初步回测测试
策略仅仅用来学习、研究,策略并未经过实盘测试,实盘慎用。
策略仅仅用于学习交流,交流策略设计思路,互相学习,有兴趣的可以挂一个富途模拟盘测试,不过个人认为网格策略仅仅适用于震荡行情,在股市熊市的时候风险比较大,虽然说股票不存在像期货那样爆仓的风险,但是遇到趋势容易被套牢。使用网格策略,网格大小和预留资金是两个挺重要的因素。
感谢阅读,感谢提出建议及意见。