互联网中如何给策略增加多图表支持

这篇文章将为大家详细讲解有关互联网中如何给策略增加多图表支持,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

创新互联建站主营长泰网站建设的网络公司,主营网站建设方案,重庆App定制开发,长泰h5小程序开发搭建,长泰网站营销推广欢迎长泰等地区企业咨询

特别是在编写趋势策略时,有时候被各种指标的触发条件弄的一头雾水,这个时候就迫切需要让数据可视化,方便分析查看。在给策略添加单一的图表时,可以直接使用「画线类库」模板画图。不过有时候需要多图表,并且是不同K线周期的,甚至指标要单独使用Y坐标轴的情况。这样就需要单独实现画图代码了。

以下给出一个范例,可以作为参考学习,我会在范例代码上逐行注释,当你读完代码,会对给策略增加图表支持有一个新的理解。

/*backtest
start: 2019-07-01 00:00:00
end: 2019-08-24 00:00:00
period: 1h
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
args: [["IsSynthesisDayKL",true]]
*/

var chart0 = {                                        
    __isStock: true,    
    // /*
    extension: {
            layout: 'single', 
            height: 300, 
    },
    // */
    title : { text : '日K线图'},                       
    xAxis: { type: 'datetime'},            
    series : [                                          
        {                                      
            type: 'candlestick',                         
            name: 'r',   
            id: 'r',                                     
            data: []                                           
        }
    ]
}

var chart1 = {                                        
    __isStock: true,    
    // /*
    extension: {
            layout: 'single', 
            height: 300, 
    },
    // */
    title : { text : 'EMA'},                       
    xAxis: { type: 'datetime'},           
    series : [                                          
        {                                      
            type: 'candlestick',                             
            name: 'r1',   
            id: 'r1',                                     
            data: []                                           
        }, {                                      
            type: 'line',           
            name: 'chart1_EMA1',          
            data: [],               
        }, {
            type: 'line',
            name: 'chart1_EMA2',          
            data: []
        }
    ]
}

var chart2 = {                                        
    __isStock: true,    
    // /*
    extension: {
            layout: 'single', 
            height: 300, 
    },
    // */
    title : { text : 'MACD'},                       
    xAxis: { type: 'datetime'},                         
    yAxis : [
        {                                           
            title: {text: '价格'},                           
            opposite: false                                 
        }, {
            title:{text: "指标轴"},
            opposite: true,  
        }
    ],
    series : [                                          
        {                                      
            type: 'candlestick',                        
            name: 'r2',   
            id: 'r2',                                     
            data: []                                           
        }, {
            type: 'line',
            yAxis: 1, 
            name: 'dif',
            data: []
        }, {
            type: 'line', 
            yAxis: 1,
            name: 'dea', 
            data: []
        }
    ]
}

function CreatePlotter (e, chart) {
    var obj = {}                      // 声明一个空对象,用于以下代码中添加方法,最后返回这个对象,即构造的绘图对象。
    
    obj.e = e                         // 参数传来的交易所对象引用,赋值给obj对象的一个属性
    obj.params = {}                   // 构造参数
    obj.params.EMA_param1 = 5         // 我们预设一些图表上指标的参数,用于指标计算时使用 ,比如一条EMA指标线参数
    obj.params.EMA_param2 = 20        // 第二条EMA指标线参数,通常参数小的叫块线,参数大的叫慢线
    obj.params.MACD_fast = 12         // MACD 参数
    obj.params.MACD_slow = 26         // MACD 参数
    obj.params.MACD_sig = 9           // MACD 参数
    
    obj.runTime = {}                  // 用于储存运行时的一些数据
    obj.runTime.arrPreBarTime = [0, 0, 0]    // 储存每个K线数据的前一个bar 的时间戳,用于对比
    
    obj.GetAllRecords = function () {              // 绘图对象的一个方法,用于获取K线数据,我们这个例子是用了三个图表同时显示,所以,这个函数同时获取三种不同周期的K线数据
        obj.r = _C(obj.e.GetRecords, PERIOD_H1)    // 第一个图表的K线数据,是1小时级别的K线数据
        Sleep(1000)  
        obj.r1 = _C(obj.e.GetRecords, PERIOD_M15)  // 第二个图表的K线数据,是15分钟级别的K线数据
        Sleep(1000)
        obj.r2 = _C(obj.e.GetRecords, PERIOD_D1)   // 第三个图表的K线数据,是日K线数据
    }
    
    obj.Run = function () {                        // 执行绘图对象的功能
        obj.Plot()                                 // 执行具体的绘图代码
    }

    obj.CalcMACD = function (r, fast, slow, sig) {       // MACD 指标计算函数,返回MACD指标数据
        if (r.length <= Math.max(fast, slow, sig)) {
            return false 
        }
        return TA.MACD(r, fast, slow, sig)
    }

    
    obj.Plot = function () {                   // 重点部分,具体的绘图代码。
        obj.GetAllRecords()                    // 每次绘图前,首先更新所有的K线数据
        var arr = [obj.r, obj.r1, obj.r2]      // 把所有K线数据放在一个数组中,遍历。
        var arrKIndex = [0, 1, 4]              // 图表对象中K线数据系列的索引
        for (var i = 0; i < arr.length; i++) { // 遍历操作
            for (var j = 0; j < arr[i].length; j++) {
                if (arr[i][j].Time == obj.runTime.arrPreBarTime[i]) {    // 当K线数据最后一bar没有更新时,我们只更新数据,不添加,可以注意看 chart.add 函数调用时,最后一个参数使用了 -1 ,意思就是更新数据,不添加。
                    chart.add(arrKIndex[i], [arr[i][j].Time, arr[i][j].Open, arr[i][j].High, arr[i][j].Low, arr[i][j].Close], -1)  
                    
                   if (i == 1) {    // 更新第二个图表中的 EMA指标数据
                        var nowR = arr[i].slice(0, j + 1)
                        var ema1 = TA.EMA(nowR, obj.params.EMA_param1)
                        var ema2 = TA.EMA(nowR, obj.params.EMA_param2)
                        if (obj.r2.length <= obj.params.EMA_param1 || obj.r2.length <= obj.params.EMA_param2 || isNaN(ema1[j]) || isNaN(ema2[j])) {
                            continue
                        }

                        chart.add(2, [arr[i][j].Time, ema1[ema1.length - 1]], -1)     
                        chart.add(3, [arr[i][j].Time, ema2[ema2.length - 1]], -1)   
                    } else if (i == 2) {     // 更新第三个图表中的 MACD 指标数据
                        var nowR = arr[i].slice(0, j + 1)
                        var macd = obj.CalcMACD(nowR, obj.params.MACD_fast, obj.params.MACD_slow, obj.params.MACD_sig)
                        if (!macd) {
                            continue
                        }

                        var dif = macd[0]
                        var dea = macd[1]
                        chart.add(5, [arr[i][j].Time, dif[dif.length - 1]], -1)   
                        chart.add(6, [arr[i][j].Time, dea[dea.length - 1]], -1)   
                    }
                } else if (arr[i][j].Time > obj.runTime.arrPreBarTime[i]) {   // 当前K线数据最后一bar比之前记录的最后bar时间戳大时,说明K线有新的bar生成,这个时候要添加新bar,并且添加新指标数据点。
                    obj.runTime.arrPreBarTime[i] = arr[i][j].Time             // 更新最后一bar时间戳的记录,用于接下来的对比,接下来的时间戳又一样了,就不会导致再添加数据,除非有新bar再产生。
                    chart.add(arrKIndex[i], [arr[i][j].Time, arr[i][j].Open, arr[i][j].High, arr[i][j].Low, arr[i][j].Close])  
                    if (i == 1) {  
                        var nowR = arr[i].slice(0, j + 1)
                        var ema1 = TA.EMA(nowR, obj.params.EMA_param1)
                        var ema2 = TA.EMA(nowR, obj.params.EMA_param2)
                        if (nowR.length <= obj.params.EMA_param1 || nowR.length <= obj.params.EMA_param2 || isNaN(ema1[ema1.length - 1]) || isNaN(ema2[ema2.length - 1])) {
                            continue
                        }

                        chart.add(2, [arr[i][j].Time, ema1[ema1.length - 1]])
                        chart.add(3, [arr[i][j].Time, ema2[ema2.length - 1]])   
                    } else if (i == 2) {
                        var nowR = arr[i].slice(0, j + 1)
                        var macd = obj.CalcMACD(nowR, obj.params.MACD_fast, obj.params.MACD_slow, obj.params.MACD_sig)
                        if (!macd) {
                            continue
                        }

                        var dif = macd[0]
                        var dea = macd[1]
                        chart.add(5, [arr[i][j].Time, dif[dif.length - 1]])   
                        chart.add(6, [arr[i][j].Time, dea[dea.length - 1]])   
                    }
                }
            }
        }
    }
    obj.Plot()

    return obj
}

function main () {
    var chart = Chart([chart0, chart1, chart2])
    chart.reset()
    
    exchange.SetContractType("quarter")
    var plotter = CreatePlotter(exchange, chart)
    while (true) {
        plotter.Run()
        Sleep(1000)
    } 
}

我们首先看main函数:

function main () {                                  // 策略入口函数,当然本策略什么也不做,没有任何交易,只是画图
    var chart = Chart([chart0, chart1, chart2])     // chart0,chart1,chart2 是预先声明好的图表配置对象,调用Chart函数,就是把图表配置载入,返回一个图表控制对象 chart
    chart.reset()                                   // 调用图表控制对象chart的reset方法,重置图表。
    
    exchange.SetContractType("quarter")             // 回测配置 选择的是OKEX期货,所以这里要设置一下合约,合约设置为季度(quarter)
    var plotter = CreatePlotter(exchange, chart)    // 调用 CreatePlotter 函数生成绘图对象 plotter
    while (true) {
        plotter.Run()                               // 执行绘图对象 plotter 成员函数 Run 绘图
        Sleep(1000)                                 // 绘图对象 plotter 是负责“如何画”,图表控制对象chart是负责具体画图,这两者中前者是我们代码实现的,后者是系统底层API函数返回的控制对象。
    } 
}

接下来就可以看CreatePlotter函数构造绘图对象时,都实现了怎样的画图功能,可以看到在代码var plotter = CreatePlotter(exchange, chart)中,构造绘图对象plotter时,传入了exchange , chart 。前者是用来获取K线数据(通过调用exchange.GetRecords),后者是用来操作图表,给图表上添加数据。

最主要的绘图部分就是Plot函数,注释已经写在代码里面。

回测运行:
互联网中如何给策略增加多图表支持

这样就可以让策略多图表显示了。

关于“互联网中如何给策略增加多图表支持”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。


网站名称:互联网中如何给策略增加多图表支持
网站URL:http://pwwzsj.com/article/goejpg.html