编写趋势策略的开发者经常和作者探讨一些指标算法,常用的指标都在talib等指标库中可以找到。但是对于一些比较冷门且实用的算法、指标就很难找到现成的。想自己动手实现又没有设计思路、设计经验,感觉无从下手。 那么本篇作者就带你通过编写设计一个简单的算法:平均K线图(Heikin-Ashi)来学习如何“手搓”算法函数。
在这里我们将所要计算的平均K线图的开盘价、最高价、最低价、收盘价简称为:avgOpen、avgHigh、avgLow、avgClose。作为参数的K线数据中的开盘价、最高价、最低价、收盘价简称为:Open、High、Low、Close。
作者拿到这个算法计算资料时详细看了一遍,发现这个计算其实并不复杂(真的很简单),计算主要分两个部分的处理。
初始Bar算法:
因为这个算法是一个迭代算法,计算当前Bar的数据时需要引用到前一个Bar的数据(很多经典指标、算法都是这种迭代计算),所以第一根Bar的计算必然是与其后的迭代计算是不同的。 根据这个指标的计算资料的描述,第一根平均K线Bar的计算方式如下:
avgOpen = (Open + Close) / 2
avgHigh = High
avgLow = Low
avgClose = (Open + High + Low + Close) / 4
后续Bar迭代算法:
除了第一根平均K线Bar之外,后续的平均K线Bar需要迭代计算,算法如下:
avgOpen = (pre_avgOpen + pre_avgClose) / 2
avgHigh = Math.max(High, avgOpen, avgClose)
avgLow = Math.min(Low, avgOpen, avgClose)
avgClose = (Open + High + Low + Close) / 4
在youquant.com上以「模板类库」形式编写、收纳这个算法,编写一个「JavaScript扩展指标库」。如果还希望“手搓”一些其它指标算法,也可以直接加入到这个模板代码中。
在策略库创建一个策略,选择策略语言为JavaScript
,选择策略类型为「模板类库」,命名为:JavaScript扩展指标库。
编写并详细注释:
// 使用JavaScript语言实现的扩展指标
/**
* calcAvgRecords: 计算Heikin-Ashi,即平均K线图
* @param {Array<Object>} records - K线Bar数组
* @returns {Array<Object>} - 平均K线数组
*/
function calcAvgRecords(records) {
// 声明、初始化一个空数组,作为函数最终返回的变量
var ret = []
// 判断传入的K线数组参数records
if (!Array.isArray(records)) {
return null
}
// 遍历K线
for (var i = 0; i < records.length; i++) {
var bar = records[i]
var avgBar = {}
if (i == 0) {
// 处理第一根Bar,计算平均K线
avgBar.Open = (bar.Open + bar.Close) / 2
avgBar.High = bar.High
avgBar.Low = bar.Low
avgBar.Close = (bar.Open + bar.High + bar.Low + bar.Close) / 4
avgBar.Time = bar.Time
} else {
// 处理其它Bar,计算平均K线
avgBar.Open = (ret[i - 1].Open + ret[i - 1].Close) / 2
avgBar.Close = (bar.Open + bar.High + bar.Low + bar.Close) / 4
avgBar.High = Math.max(bar.High, avgBar.Open, avgBar.Close)
avgBar.Low = Math.min(bar.Low, avgBar.Open, avgBar.Close)
avgBar.Time = bar.Time
}
// 将计算出的平均K线Bar,依次放入数组ret中
ret.push(avgBar)
}
return ret
}
// 导出函数
$.CalcAvgRecords = calcAvgRecords
// 测试函数
function main() {
var chart = KLineChart({})
while (true) {
if (exchange.IO("status")) {
// 设置螺纹钢主力合约
exchange.SetContractType("rb888")
// 获取K线数据
var r = exchange.GetRecords()
// 使用我们编写的算法函数,计算平均K线
var avgRecords = $.CalcAvgRecords(r)
if (avgRecords) {
// 使用KLineChart函数创建的对象画图,画出平均K线
avgRecords.forEach(function(bar, index) {
chart.begin(bar)
chart.close()
})
}
}
Sleep(500)
}
}
运行这个模板类库,执行main
函数中的获取数据、画图等操作,计算出了平均K线数据并画图。
该代码用于教学,可以根据具体需求随意扩展、修改。