以平均K线图(Heikin-Ashi)算法为例教你写FMZ扩展指标库

Author: 雨幕(youquant), Created: 2023-06-25 15:09:43, Updated: 2023-06-26 09:50:10

img

以平均K线图(Heikin-Ashi)算法为例教你写FMZ扩展指标库

编写趋势策略的开发者经常和作者探讨一些指标算法,常用的指标都在talib等指标库中可以找到。但是对于一些比较冷门且实用的算法、指标就很难找到现成的。想自己动手实现又没有设计思路、设计经验,感觉无从下手。 那么本篇作者就带你通过编写设计一个简单的算法:平均K线图(Heikin-Ashi)来学习如何“手搓”算法函数。

平均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
    

设计实现

在FMZ.CN上以「模板类库」形式编写、收纳这个算法,编写一个「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线数据并画图。

img

该代码用于教学,可以根据具体需求随意扩展、修改。


更多内容