资源加载中... loading...

Chart

自定义图表画图函数。

图表对象。 object

Chart(options)

options参数为图表配置。 Chart()函数的参数options是可以JSON序列化的HighStocksHighcharts.StockChart参数。 比原生的参数增加一个__isStock属性,如果指定__isStock:false,则显示为普通图表。 如果设置__isStock属性为假值例如:false,即使用的图表为Highcharts图表。 如果设置__isStock属性为真值例如:true,即使用的图表为Highstocks图表(默认__isStock为真值,例如true)。 可以查询HighStocks图表库。 options true object、object数组

function main() {
    var cfgA = {
        extension: {
            layout: 'single', // 不参于分组,单独显示, 默认为分组 'group'
            height: 300, // 指定高度
        },
        title: {
            text: '盘口图表'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: '买一',
            data: [],
        }, {
            name: '卖一',
            data: [],
        }]
    }
    var cfgB = {
        title: {
            text: '差价图'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: '差价',
            type: 'column',
            data: [],
        }]
    }            

    var cfgC = {
        __isStock: false,
        title: {
            text: '饼图'
        },
        series: [{
            type: 'pie',
            name: 'one',
            data: [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]  // 指定初始数据后不需要用add函数更新, 直接更改图表配置就可以更新序列.
        }]
    };
    var cfgD = {
        extension: {
            layout: 'single',
            col: 8, // 指定宽度占的单元值, 总值 为12
            height: '300px',
        },
        title: {
            text: '盘口图表'
        },
        xAxis: {
            type: 'datetime'
        },
        series: [{
            name: '买一',
            data: [],
        }, {
            name: '卖一',
            data: [],
        }]
    }
    var cfgE = {
        __isStock: false,
        extension: {
            layout: 'single',
            col: 4,
            height: '300px',
        },
        title: {
            text: '饼图2'
        },
        series: [{
            type: 'pie',
            name: 'one',
            data: [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]
        }]
    };            

    var chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE]);
    chart.reset()
        // 为饼图清加一个数点,add只能更新通过add方式添加的数据点, 内置的数据点无法后期更新
    chart.add(3, {
        name: "ZZ",
        y: Math.random() * 100
    });
    while (true) {
        Sleep(1000)
        exchange.SetContractType("rb888")
        var ticker = exchange.GetTicker()
        if (!ticker) {
            continue;
        }
        var diff = ticker.Sell - ticker.Buy
        cfgA.subtitle = {
            text: '买一 ' + ticker.Buy + ', 卖一 ' + ticker.Sell,
        };
        cfgB.subtitle = {
            text: '价差 ' + diff,
        };            

        chart.add([0, [new Date().getTime(), ticker.Buy]]);
        chart.add([1, [new Date().getTime(), ticker.Sell]]);
        // 相当于更新第二个图表的第一个数据序列
        chart.add([2, [new Date().getTime(), diff]]);
        chart.add(4, [new Date().getTime(), ticker.Buy]);
        chart.add(5, [new Date().getTime(), ticker.Buy]);
        cfgC.series[0].data[0][1] = Math.random() * 100;
        cfgE.series[0].data[0][1] = Math.random() * 100;
        // update实际上等于重置了图表的配置
        chart.update([cfgA, cfgB, cfgC, cfgD, cfgE]);
    }
}            
import random
import time
def main():
    cfgA = {
        "extension" : {
            "layout" : "single", 
            "height" : 300,
            "col" : 8
        }, 
        "title" : {
            "text" : "盘口图表"
        },
        "xAxis" : {
            "type" : "datetime" 
        }, 
        "series" : [{
            "name" : "买一",
            "data" : []
        }, {
            "name" : "卖一", 
            "data" : []
        }]
    }                

    cfgB = {
        "title" : {
            "text" : "差价图"
        }, 
        "xAxis" : {
            "type" : "datetime",
        }, 
        "series" : [{
            "name" : "差价", 
            "type" : "column", 
            "data" : []
        }]
    }                

    cfgC = {
        "__isStock" : False,
        "title" : {
            "text" : "饼图"
        }, 
        "series" : [{
            "type" : "pie", 
            "name" : "one", 
            "data" : [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25],
            ]
        }]
    }                

    cfgD = {
        "extension" : {
            "layout" : "single",
            "col" : 8,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "盘口图表"
        }, 
        "series" : [{
            "name" : "买一", 
            "data" : []
        }, {
            "name" : "卖一",
            "data" : []
        }]
    }                

    cfgE = {
        "__isStock" : False, 
        "extension" : {
            "layout" : "single", 
            "col" : 4,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "饼图2"
        },
        "series" : [{
            "type" : "pie",
            "name" : "one", 
            "data" : [
                ["A", 25], 
                ["B", 25], 
                ["C", 25], 
                ["D", 25]
            ]
        }]
    }
    
    chart = Chart([cfgA, cfgB, cfgC, cfgD, cfgE])
    chart.reset()
    chart.add(3, {
        "name" : "ZZ",
        "y" : random.random() * 100
    })
    
    while True:
        Sleep(1000)
        exchange.SetContractType("rb888")
        ticker = exchange.GetTicker()
        if not ticker :
            continue
        diff = ticker["Sell"] - ticker["Buy"]
        cfgA["subtitle"] = {
            "text" : "买一" + str(ticker["Buy"]) + "卖一" + str(ticker["Sell"])
        }
        cfgB["subtitle"] = {
            "text" : "价差 " + str(diff)
        }
        
        chart.add(0, [time.time() * 1000, ticker["Buy"]])
        chart.add(1, [time.time() * 1000, ticker["Sell"]])
        chart.add(2, [time.time() * 1000, diff])
        chart.add(4, [time.time() * 1000, ticker["Buy"]])
        chart.add(5, [time.time() * 1000, ticker["Buy"]])
        cfgC["series"][0]["data"][0][1] = random.random() * 100
        cfgE["series"][0]["data"][0][1] = random.random() * 100
void main() {
    json cfgA = R"({
        "extension" : {
            "layout" : "single", 
            "height" : 300,
            "col" : 8
        }, 
        "title" : {
            "text" : "盘口图表"
        },
        "xAxis" : {
            "type" : "datetime" 
        }, 
        "series" : [{
            "name" : "买一",
            "data" : []
        }, {
            "name" : "卖一", 
            "data" : []
        }]
    })"_json;                

    json cfgB = R"({
        "title" : {
            "text" : "差价图"
        }, 
        "xAxis" : {
            "type" : "datetime"
        }, 
        "series" : [{
            "name" : "差价", 
            "type" : "column", 
            "data" : []
        }]
    })"_json;    
    
    json cfgC = R"({
        "__isStock" : false,
        "title" : {
            "text" : "饼图"
        }, 
        "series" : [{
            "type" : "pie", 
            "name" : "one", 
            "data" : [
                ["A", 25],
                ["B", 25],
                ["C", 25],
                ["D", 25]
            ]
        }]
    })"_json;    
    
    json cfgD = R"({
        "extension" : {
            "layout" : "single",
            "col" : 8,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "盘口图表"
        }, 
        "series" : [{
            "name" : "买一", 
            "data" : []
        }, {
            "name" : "卖一",
            "data" : []
        }]
    })"_json;    
    
    json cfgE = R"({
        "__isStock" : false, 
        "extension" : {
            "layout" : "single", 
            "col" : 4,
            "height" : "300px"
        }, 
        "title" : {
            "text" : "饼图2"
        },
        "series" : [{
            "type" : "pie",
            "name" : "one", 
            "data" : [
                ["A", 25], 
                ["B", 25], 
                ["C", 25], 
                ["D", 25]
            ]
        }]
    })"_json;            

    auto chart = Chart({cfgA, cfgB, cfgC, cfgD, cfgE});
    chart.reset();
    json zz = R"({
        "name" : "ZZ", 
        "y" : 0
    })"_json;
    zz["y"] = rand() % 100;
    chart.add(3, zz);
    
    while(true) {
        Sleep(1000);
        exchange.SetContractType("rb888");
        auto ticker = exchange.GetTicker();
        if(!ticker.Valid) {
            continue;
        }
        auto diff = ticker.Sell - ticker.Buy;
        json cfgASubTitle = R"({"text" : ""})"_json;
        cfgASubTitle["text"] = format("买一 %f , 卖一 %f", ticker.Buy, ticker.Sell);
        cfgA["subtitle"] = cfgASubTitle;
        
        json cfgBSubTitle = R"({"text" : ""})"_json;
        cfgBSubTitle["text"] = format("价差 %f", diff);
        cfgB["subtitle"] = cfgBSubTitle;            

        chart.add(0, {Unix() * 1000, ticker.Buy});
        chart.add(1, {Unix() * 1000, ticker.Sell});
        chart.add(2, {Unix() * 1000, diff});
        chart.add(4, {Unix() * 1000, ticker.Buy});
        chart.add(5, {Unix() * 1000, ticker.Buy});
        cfgC["series"][0]["data"][0][1] = rand() % 100;
        cfgE["series"][0]["data"][0][1] = rand() % 100;
        chart.update({cfgA, cfgB, cfgC, cfgD, cfgE});
    }
}

多图表画图配置:

  • extension.layout属性 如果设置此属性,值为"single",则图表不会叠加(不会以分页标签方式显示),会单独显示(平铺显示)。
  • extension.height属性 此属性用于设置图表的高度,值可以为数值类型,或以"300px"方式设置。
  • extension.col属性 此属性用于设置图表的宽度,页面宽度一共划分为12个单元,设置8即该图表占用8个单元宽度。
// 这个chart在JavaScript语言中是对象,在使用Chart函数之前我们需要声明一个配置图表的对象变量chart
var chart = {                                           
    // 该字段标记图表是否为一般图表,有兴趣的可以改成false运行看看
    __isStock: true,                                    
    // 缩放工具
    tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},    
    // 标题
    title : { text : '差价分析图'},                       
    // 选择范围
    rangeSelector: {                                    
        buttons:  [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
        selected: 0,
        inputEnabled: false
    },
    // 坐标轴横轴即:x轴,当前设置的类型是:时间
    xAxis: { type: 'datetime'},                         
    // 坐标轴纵轴即:y轴,默认数值随数据大小调整
    yAxis : {                                           
        // 标题
        title: {text: '差价'},                           
        // 是否启用右边纵轴
        opposite: false                                 
    },
    // 数据系列,该属性保存的是各个数据系列(线,K线图,标签等...)
    series : [                                          
        // 索引为0,data数组内存放的是该索引系列的数据
        {name : "line1", id : "线1,buy1Price", data : []},                          
        // 索引为1,设置了dashStyle:'shortdash'即:设置虚线
        {name : "line2", id : "线2,lastPrice", dashStyle : 'shortdash', data : []}  
    ]
}
function main(){
    // 调用Chart函数,初始化图表
    var ObjChart = Chart(chart)         
    // 清空
    ObjChart.reset()                      
    while(true){
        // 判断连接期货公司前置机是否成功。股票证券无需使用exchange.IO("status")判断连接状态
        if (!exchange.IO("status")) {
            Sleep(1000)
            continue
        }
        exchange.SetContractType("rb888")

        // 获取本次轮询的时间戳,即一个毫秒的时间戳。用来确定写入到图表的X轴的位置
        var nowTime = new Date().getTime()
        // 获取行情数据
        var ticker = _C(exchange.GetTicker)
        // 从行情数据的返回值取得买一价
        var buy1Price = ticker.Buy    
        // 取得最后成交价,为了2条线不重合在一起,我们加1
        var lastPrice = ticker.Last + 1
        // 用时间戳作为X值,买一价作为Y值传入索引0的数据序列
        ObjChart.add(0, [nowTime, buy1Price])
        // 同上
        ObjChart.add(1, [nowTime, lastPrice])
        Sleep(2000)
    }
}
import time
chart = {
    "__isStock" : True,
    "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"},  
    "title" : {"text" : "差价分析图"}, 
    "rangeSelector" : {
        "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], 
        "selected": 0,
        "inputEnabled": False 
    }, 
    "xAxis": {"type": "datetime"}, 
    "yAxis": {
        "title": {"text": "差价"},
        "opposite": False
    },
    "series": [{
        "name": "line1", "id": "线1,buy1Price", "data": []
    }, {
        "name": "line2", "id": "线2,lastPrice", "dashStyle": "shortdash", "data": []
    }]
}
def main():
    ObjChart = Chart(chart)
    ObjChart.reset()
    while True:
        if not exchange.IO("status"):
            Sleep(1000)
            continue
        exchange.SetContractType("rb888")
        
        nowTime = time.time() * 1000
        ticker = exchange.GetTicker()
        buy1Price = ticker["Buy"]
        lastPrice = ticker["Last"] + 1
        ObjChart.add(0, [nowTime, buy1Price])
        ObjChart.add(1, [nowTime, lastPrice])
        Sleep(2000)
void main() {
    // C++编写策略时,尽量不要声明非基础类型的全局变量,所以图表配置对象声明在main函数内
    json chart = R"({
        "__isStock" : true,
        "tooltip" : {"xDateFormat" : "%Y-%m-%d %H:%M:%S, %A"},  
        "title" : {"text" : "差价分析图"}, 
        "rangeSelector" : {
            "buttons" : [{"type": "count", "count": 1, "text": "1h"}, {"type": "hour", "count": 3, "text": "3h"}, {"type": "hour", "count": 8, "text": "8h"}, {"type": "all", "text": "All"}], 
            "selected": 0,
            "inputEnabled": false 
        }, 
        "xAxis": {"type": "datetime"}, 
        "yAxis": {
            "title": {"text": "差价"},
            "opposite": false
        },
        "series": [{
            "name": "line1", "id": "线1,buy1Price", "data": []
        }, {
            "name": "line2", "id": "线2,lastPrice", "dashStyle": "shortdash", "data": []
        }]
    })"_json;
    auto ObjChart = Chart(chart);
    ObjChart.reset();
    while(true) {
        if (exchange.IO("status") == 0) {
            Sleep(1000);
            continue;
        }
        exchange.SetContractType("rb888");
        
        auto nowTime = Unix() * 1000;
        auto ticker = exchange.GetTicker();
        auto buy1Price = ticker.Buy;
        auto lastPrice = ticker.Last + 1.0;
        ObjChart.add(0, {nowTime, buy1Price});
        ObjChart.add(1, {nowTime, lastPrice});
        Sleep(2000);
    }
}

简单的画图例子:

// 用于初始化图表的对象
var chart = {                                   
    // 图表标题
    title: {text: "line数值触发 plotLines 值"},   
    // Y轴相关设置
    yAxis: {                                    
        // 垂直于Y轴的水平线,用作触发线,是一个结构数组,可以设置多条触发线
        plotLines: [{                           
            // 触发线的值,设置多少这条线就在相应的数值位置显示
            value: 0,                           
            // 设置触发线的颜色
            color: 'red',                       
            // 宽度
            width: 2,                           
            // 显示的标签
            label: {                            
                // 标签文本
                text: '触发值',                  
                // 标签位置居中
                align: 'center'                 
            }
        }]
    },
    // X轴相关设置,这里设置类型是时间轴
    xAxis: {type: "datetime"},                  
    series: [
        {name: "sin", type: "spline", data: []},
        // 这个是比较重要的数据系列,可以设置多个数据系列,根据数组索引控制
        {name: "cos", type: "spline", data: []}
    ]  
}
function main(){
    // 圆周率
    var pi = 3.1415926535897
    // 用于记录时间戳的变量
    var time = 0                   
    // 角度
    var angle = 0                        
    // 坐标y值,用于接收正弦值、余弦值
    var y = 0          
    // 调用API接口用chart对象初始化图表
    var objChart = Chart(chart)        
    // 初始,清空图表
    objChart.reset()
    // 设置触发线的值为1
    chart.yAxis.plotLines[0].value = 1
    // 循环
    while(true){                          
        // 获取当前时刻的时间戳
        time = new Date().getTime() 
        // 每500ms角度angle增加5度,计算正弦值
        y = Math.sin(angle * 2 * pi / 360)
        // 把计算出来的y值写入图表相应索引的数据系列,add函数的第一个参数为指定的数据系列索引
        objChart.add(0, [time, y])
        // 计算余弦值
        y = Math.cos(angle * 2 * pi / 360)
        objChart.add(1, [time, y])
        // 增加5度
        angle += 5
        // 暂停5秒,以免画图太频繁,数据增长过快
        Sleep(5000)     
    }
}
import math
import time
chart = {
    "title": {"text": "line数值触发 plotLines 值"}, 
    "yAxis": {
        "plotLines": [{
            "value": 0,
            "color": "red",
            "width": 2,
            "label": {
                "text": "触发值", 
                "align": "center"
            }
        }]
    },
    "xAxis": {"type": "datetime"},
    "series": [{"name": "sin", "type": "spline", "data": []},
               {"name": "cos", "type": "spline", "data": []}]
}
def main():
    pi = 3.1415926535897
    ts = 0
    angle = 0
    y = 0
    objChart = Chart(chart)
    objChart.reset()
    chart["yAxis"]["plotLines"][0]["value"] = 1
    while True:
        ts = time.time() * 1000
        y = math.sin(angle * 2 * pi / 360)
        objChart.add(0, [ts, y])
        y = math.cos(angle * 2 * pi / 360)
        objChart.add(1, [ts, y])
        angle += 5
        Sleep(5000)
void main() {
    json chart = R"({
        "title": {"text": "line数值触发 plotLines 值"}, 
        "yAxis": {
            "plotLines": [{
                "value": 0,
                "color": "red",
                "width": 2,
                "label": {
                    "text": "触发值", 
                    "align": "center"
                }
            }]
        },
        "xAxis": {"type": "datetime"},
        "series": [{"name": "sin", "type": "spline", "data": []},
                   {"name": "cos", "type": "spline", "data": []}]     
    })"_json;            

    auto pi = 3.1415926535897;
    auto ts = 0;
    auto angle = 0.0;
    auto y = 0.0;
    auto objChart = Chart(chart);
    objChart.reset();
    chart["yAxis"]["plotLines"][0]["value"] = 1;
    while(true) {
        ts = Unix() * 1000;
        y = sin(angle * 2 * pi / 360);
        objChart.add(0, {ts, y});
        y = cos(angle * 2 * pi / 360);
        objChart.add(1, {ts, y});
        angle += 5;
        Sleep(5000);
    }
}

三角函数曲线画图例子:

var chartCfg = {
    subtitle: {
        text: "subtitle",
    },
    yAxis: [{
        height: "40%",
        lineWidth: 2,
        title: {
            text: 'PnL',
        },
        tickPixelInterval: 20,
        minorGridLineWidth: 1,
        minorTickWidth: 0,
        opposite: true,
        labels: {
            align: "right",
            x: -3,
        }
    }, {
        title: {
            text: 'Profit',
        },
        top: "42%",
        height: "18%",
        offset: 0,
        lineWidth: 2
    }, {
        title: {
            text: 'Vol',
        },
        top: '62%',
        height: '18%',
        offset: 0,
        lineWidth: 2
    }, {
        title: {
            text: 'Asset',
        },
        top: '82%',
        height: '18%',
        offset: 0,
        lineWidth: 2
    }],
    series: [{
        name: 'PnL',
        data: [],
        id: 'primary',
        tooltip: {
            xDateFormat: '%Y-%m-%d %H:%M:%S'
        },
        yAxis: 0
    }, {
        type: 'column',
        lineWidth: 2,
        name: 'Profit',
        data: [],
        yAxis: 1,
    }, {
        type: 'column',
        name: 'Trade',
        data: [],
        yAxis: 2
    }, {
        type: 'area',
        step: true,
        lineWidth: 0,
        name: 'Long',
        data: [],
        yAxis: 2
    }, {
        type: 'area',
        step: true,
        lineWidth: 0,
        name: 'Short',
        data: [],
        yAxis: 2
    }, {
        type: 'line',
        step: true,
        color: '#5b4b00',
        name: 'Asset',
        data: [],
        yAxis: 3
    }, {
        type: 'pie',
        innerSize: '70%',
        name: 'Random',
        data: [],
        center: ['3%', '6%'],
        size: '15%',
        dataLabels: {
            enabled: false
        },
        startAngle: -90,
        endAngle: 90,
    }],
};            

function main() {
    let c = Chart(chartCfg);
    let preTicker = null;
    while (true) {
        if (!exchange.IO("status")) {
            Sleep(1000)
            continue
        }
        exchange.SetContractType("rb888")

        let t = exchange.GetTicker();
        
        c.add(0, [t.Time, t.Last]); // PnL
        c.add(1, [t.Time, preTicker ? t.Last - preTicker.Last : 0]); // profit
        let r = Math.random();
        var pos = parseInt(t.Time/86400);
        c.add(2, [t.Time, pos/2]); // Vol
        c.add(3, [t.Time, r > 0.8 ? pos : null]); // Long
        c.add(4, [t.Time, r < 0.8 ? -pos : null]); // Short
        c.add(5, [t.Time, Math.random() * 100]); // Asset
        // update pie
        chartCfg.series[chartCfg.series.length-1].data = [
            ["A", Math.random()*100],
            ["B", Math.random()*100],
         ];
        c.update(chartCfg)
        preTicker = t;
    }
}
import random            

chartCfg = {
    "subtitle": {
        "text": "subtitle"
    },
    "yAxis": [{
        "height": "40%",
        "lineWidth": 2,
        "title": {
            "text": 'PnL'
        },
        "tickPixelInterval": 20,
        "minorGridLineWidth": 1,
        "minorTickWidth": 0,
        "opposite": True,
        "labels": {
            "align": "right",
            "x": -3
        }
    }, {
        "title": {
            "text": 'Profit'
        },
        "top": "42%",
        "height": "18%",
        "offset": 0,
        "lineWidth": 2
    }, {
        "title": {
            "text": 'Vol'
        },
        "top": '62%',
        "height": '18%',
        "offset": 0,
        "lineWidth": 2
    }, {
        "title": {
            "text": 'Asset'
        },
        "top": '82%',
        "height": '18%',
        "offset": 0,
        "lineWidth": 2
    }],
    "series": [{
        "name": 'PnL',
        "data": [],
        "id": 'primary',
        "tooltip": {
            "xDateFormat": '%Y-%m-%d %H:%M:%S'
        },
        "yAxis": 0
    }, {
        "type": 'column',
        "lineWidth": 2,
        "name": 'Profit',
        "data": [],
        "yAxis": 1
    }, {
        "type": 'column',
        "name": 'Trade',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'area',
        "step": True,
        "lineWidth": 0,
        "name": 'Long',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'area',
        "step": True,
        "lineWidth": 0,
        "name": 'Short',
        "data": [],
        "yAxis": 2
    }, {
        "type": 'line',
        "step": True,
        "color": '#5b4b00',
        "name": 'Asset',
        "data": [],
        "yAxis": 3
    }, {
        "type": 'pie',
        "innerSize": '70%',
        "name": 'Random',
        "data": [],
        "center": ['3%', '6%'],
        "size": '15%',
        "dataLabels": {
            "enabled": False
        },
        "startAngle": -90,
        "endAngle": 90
    }]
}            

def main():
    c = Chart(chartCfg)
    preTicker = None
    while True:
        if not exchange.IO("status"):
            Sleep(1000)
            continue
        exchange.SetContractType("rb888")

        t = exchange.GetTicker()
        c.add(0, [t["Time"], t["Last"]])
        profit = t["Last"] - preTicker["Last"] if preTicker else 0
        c.add(1, [t["Time"], profit])
        r = random.random()
        pos = t["Time"] / 86400
        c.add(2, [t["Time"], pos / 2])
        long = pos if r > 0.8 else None
        c.add(3, [t["Time"], long])
        short = -pos if r < 0.8 else None
        c.add(4, [t["Time"], short])
        c.add(5, [t["Time"], random.random() * 100])            

        # update pie
        chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [
            ["A", random.random() * 100], 
            ["B", random.random() * 100]
        ]
        c.update(chartCfg)
        preTicker = t
void main() {
    json chartCfg = R"({
        "subtitle": {
            "text": "subtitle"
        },
        "yAxis": [{
            "height": "40%",
            "lineWidth": 2,
            "title": {
                "text": "PnL"
            },
            "tickPixelInterval": 20,
            "minorGridLineWidth": 1,
            "minorTickWidth": 0,
            "opposite": true,
            "labels": {
                "align": "right",
                "x": -3
            }
        }, {
            "title": {
                "text": "Profit"
            },
            "top": "42%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }, {
            "title": {
                "text": "Vol"
            },
            "top": "62%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }, {
            "title": {
                "text": "Asset"
            },
            "top": "82%",
            "height": "18%",
            "offset": 0,
            "lineWidth": 2
        }],
        "series": [{
            "name": "PnL",
            "data": [],
            "id": "primary",
            "tooltip": {
                "xDateFormat": "%Y-%m-%d %H:%M:%S"
            },
            "yAxis": 0
        }, {
            "type": "column",
            "lineWidth": 2,
            "name": "Profit",
            "data": [],
            "yAxis": 1
        }, {
            "type": "column",
            "name": "Trade",
            "data": [],
            "yAxis": 2
        }, {
            "type": "area",
            "step": true,
            "lineWidth": 0,
            "name": "Long",
            "data": [],
            "yAxis": 2
        }, {
            "type": "area",
            "step": true,
            "lineWidth": 0,
            "name": "Short",
            "data": [],
            "yAxis": 2
        }, {
            "type": "line",
            "step": true,
            "color": "#5b4b00",
            "name": "Asset",
            "data": [],
            "yAxis": 3
        }, {
            "type": "pie",
            "innerSize": "70%",
            "name": "Random",
            "data": [],
            "center": ["3%", "6%"],
            "size": "15%",
            "dataLabels": {
                "enabled": false
            },
            "startAngle": -90,
            "endAngle": 90
        }]
    })"_json;
    
    Chart c = Chart(chartCfg);
    Ticker preTicker;
    while(true) {
        if (exchange.IO("status") != 0) {
            Sleep(1000);
            continue;
        }
        exchange.SetContractType("rb888");

        auto t = exchange.GetTicker();
        c.add(0, {t.Time, t.Last});
        auto profit = preTicker.Valid ? t.Last - preTicker.Last : 0;
        c.add(1, {t.Time, profit});    
        auto r = rand() % 100;
        auto pos = t.Time / 86400.0;
        c.add(2, {t.Time, pos / 2.0});
        auto longPos = r > 0.8 ? pos : NULL;
        c.add(3, {t.Time, longPos});
        auto shortPos = r < 0.8 ? -pos : NULL;
        c.add(4, {t.Time, shortPos});
        c.add(5, {t.Time, rand() % 100});
        
        // update pie 
        json pie = R"([["A", 0], ["B", 0]])"_json;
        pie[0][1] = rand() % 100;
        pie[1][1] = rand() % 100;
        chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie;
        
        c.update(chartCfg);
        preTicker = t;
    }
}            

使用混合图表的复杂例子:

// update pie
chartCfg.series[chartCfg.series.length-1].data = [
    ["A", Math.random()*100],
    ["B", Math.random()*100],
];
c.update(chartCfg)
# update pie
chartCfg["series"][len(chartCfg["series"]) - 1]["data"] = [
    ["A", random.random() * 100], 
    ["B", random.random() * 100]
]
c.update(chartCfg)
// update pie 
json pie = R"([["A", 0], ["B", 0]])"_json;
pie[0][1] = rand() % 100;
pie[1][1] = rand() % 100;
chartCfg["series"][chartCfg["series"].size() - 1]["data"] = pie;
c.update(chartCfg);

图表中pie类型的图是没有时间轴的图表,在更新数据时需要直接更新图表配置。 例如以上范例中的代码,更新数据后使用c.update(chartCfg)更新图表,如下所示:

Chart()函数返回一个图表对象,该对象有4个方法:add()reset()update()del()

  • 1、update()方法: update()方法可以更新图表配置信息,该方法的参数为Chart图表配置对象(JSON)。

  • 2、del()方法: del()方法可以根据传入的series参数,删除指定索引的数据系列。

  • 3、add()方法: add()方法可以向图表中写入数据,参数依次为:

    • series:用于设置数据系列索引,是整数。
    • data:用于设置写入的具体数据,是一个数组。
    • index(可选):用于设置数据索引,是整数。指定修改数据的具体索引位置,支持使用负数表示,设置为-1指数据集的最后一个数据。 例如画线时,修改线的最后一个点上的数据:chart.add(0, [1574993606000, 13.5], -1),即更改图表series[0].data的倒数第一个点的数据。 不设置index参数表示向当前数据系列(series)最后添加数据。
  • 4、reset()方法: reset()方法用于清空图表数据,reset()方法可以带一个参数remain用于指定保留数据的条数。不传参数remain表示清除全部数据。

{@fun/Log/KLineChart KLineChart}

EnableLog KLineChart