Entwerfen Sie eine Bibliothek mit mehreren Diagrammen

Schriftsteller:- Ich bin ein Idiot., Erstellt: 2022-04-06 09:16:48, aktualisiert:

Entwerfen Sie eine Bibliothek mit mehreren Diagrammen

Diese Art von Bibliothek wird oft verwendet, um Diagramme und Grafiken zu erstellen, wenn man Strategien schreibt und entwirft.Plotting-Bibliothek(Benutzer, die nicht mit dem Konzept der Template-Bibliothek auf FMZ vertraut sind, können die FMZ API-Dokumentation überprüfen), die für Plotting-Operationen sehr praktisch ist. Für Szenarien, die mehrere Diagramme erfordern, kann diese Template-Bibliothek jedoch nicht den Anforderungen entsprechen. Dann lernen wir die Designideen dieser Plotting-Bibliothek und entwerfen auf dieser Grundlage eine Multi-Chart-Version der Plotting-Bibliothek.

Entwerfen der Exportfunktionen von Template Library

Wir können aus dem Exportfunktionsdesign von plot Library lernen, ähnliche Exportfunktionen für die Multi-Chart-Plotting-Bibliothek zu entwerfen.

  • $. PlotMultRecords Für die Zeichnung von K-Liniendiagrammen verwendet, entworfene Parameter: cfgName, seriesName, records, extension。 cfgName: als einziges Diagramm, der Name des konfigurierten Objekts;
    SerieName: Name der Datenreihe, für die derzeit K-Linien gezeichnet werden müssen; Aufzeichnungen: die übermittelten K-Liniendaten; Erweiterung: Informationen über die Grafikdimensionenkonfiguration, z. B.: pass{layout: 'single', col: 6, height: '600px'}, d. h. das Diagramm mit dem konfigurierten Objektnamen von cfgName nur mit Breite: 6, Höhe: 600px anzeigen lassen.

  • $. PlotMultLine Wird verwendet, um Linien zu zeichnen, entworfene Parameter: cfgName, seriesName, Dot, ts, Erweiterung cfgName: als einzelnes Diagramm der Name des konfigurierten Objekts; SerieName: der Name der Datenreihe, für die gerade Linien gezogen werden müssen; Punkt: der Ordnungswert des Punktes auf den zu zeichnenden Linien; ts: Zeitstempel, d. h. der Wert auf der X-Zeitachse; Erweiterung: Informationen zur Dimensionskonfiguration des Diagramms.

  • $. PlotMultHLine Verwendet zur Zeichnung horizontaler Linien; entworfene Parameter: cfgName, Wert, Etikett, Farbe, Stil cfgName: das konfigurierte Objekt im Diagramm; Wert: der Ordnungswert der horizontalen Linie; Etikett: der Text, der auf der horizontalen Linie angezeigt wird; Farbe: Linienfarbe; Stil: Linienstil, zum Beispiel:Solid ShortDash ShortDot ShortDashDot ShortDashDotDot Dot Dash LongDash DashDot LongDashDot LongDashDotDot.

  • $. PlotMultTitle Wird verwendet, um den Titel und den Untertitel des Diagramms zu ändern; entworfene Parameter: cfgName, title, chartTitle cfgName: der konfigurierte Objektname; Titel: Untertitel ChartTitle: der Titel der Karte.

  • $. PlotMultFlag Wird verwendet, um Flaggen zu zeichnen; entworfene Parameter: cfgName, seriesName, ts, Text, Titel, Form, Farbe, onSeriesName cfgName: das konfigurierte Objekt im Diagramm; SerieName: der Name der Datenreihe; ts: Zeitstempel; Text: der Text in der Flagge; Titel: der Titel der Flagge; Form: die Form der Flagge; Farbe: die Farbe der Flagge; onSeriesName: Es hängt davon ab, auf welcher Datenserie angezeigt werden soll; der Wert ist die ID der Datenserie.

  • - Ich habe keine Ahnung. Wird verwendet, um das konfigurierte Objektarray des Diagramms zurückzugeben.

Konstruktionsprüffunktionen

Für ein einfaches Verständnis habe ich direkt auf die Testfunktionen Hinweise geschrieben und erklärt, was jeder Funktionsruf tut.

// test
function main() {
    LogReset(10)
    var i = 0 
    var prePrintTs = 0

    while (true) {
        var r = exchange.GetRecords()   // Get K-line data
        var t = exchange.GetTicker()    // Get the real-time tick data 

        $.PlotMultRecords("chart1", "kline1", r, {layout: 'single', col: 6, height: '600px'})   // Create a K-line chart named chart1, and display it solely; the width is 6, and the height is 600px; the K-line data series name is kline1, and use r obtained above as the data source to draw the chart
        $.PlotMultRecords("chart2", "kline2", r, {layout: 'single', col: 6, height: '600px'})   // Craete the second K-line chart, named chart2
        $.PlotMultLine("chart2", "line1", t.Last, r[r.length - 1].Time)  // Add a line to the K-line chart, namely chart2, the name of the data series is line1, and use the Last of the real-time tick data as the Y value of the dot on the line. The timestamp of the last BAR of the K-line data is used as the X value
        $.PlotMultLine("chart3", "line2", t.Last)   // Create a chart named chart3 that only draws lines, with data series name line2; use the Last of real-time tick data to draw a dot at the current time (X value) (t.Last is Y value); note that the chart is not displayed solely
        $.PlotMultLine("chart6", "line6", t.Time)   // Create a chart chart6 that only draws lines; note that the chart is not displayed solely, it will be displayed with chart3 on pagination 
        $.PlotMultLine("chart4", "line3", t.Sell, new Date().getTime(), {layout: 'single', col: 4, height: '300px'})  // Create a chart named chart4 that only draws lines, solely displayed, width 4, height 300px
        $.PlotMultLine("chart5", "line4", t.Volume, new Date().getTime(), {layout: 'single', col: 8, height: '300px'})  // Create a chart named chart5 that only draws lines, solely displayed, width 8, height 300px  

        $.PlotMultHLine("chart1", r[r.length - 1].Close, "HLine1", "blue", "ShortDot")   // Add horizontal lines in chart1
        $.PlotMultHLine("chart4", t.Sell, "HLine2", "green")  // Add horizontal lines in chart4
        $.PlotMultTitle("chart3", "change : chart3->test1", "test1")   // Modify the title of chart3

        var ts = new Date().getTime()
        if (ts - prePrintTs > 1000 * 20) {
            prePrintTs = ts 
            // when triggered, draw a flag on chart3
            $.PlotMultFlag("chart3", "flag1", new Date().getTime(), "flag test", "flag1")
        }
        
        if (i == 10) {
            Log("i == 10")
            // when triggered, draw a flag on chart4, and chart1
            $.PlotMultFlag("chart4", "flag2", new Date().getTime(), "flag test", "flag2")
            $.PlotMultFlag("chart1", "flag3", new Date().getTime(), "flag test", "flag3", "squarepin", "green", "kline1")
        } else if (i == 20) {
            Log("i == 20")
            // when triggered, add a line on chart1, but only draw a dot of the line; X coordinate is timestamp, and Y coordinate is the value of t.Last 
            $.PlotMultLine("chart1", "line5", t.Last, r[r.length - 1].Time)
        } else if (i == 30) {
            Log("i == 30")
            // when triggered, draw a flag on chart2 
            $.PlotMultFlag("chart2", "flag4", new Date().getTime(), "flag test", "flag4", "circlepin", "black", "kline2")
        }
        
        Sleep(1000 * 5)
        i++
    }
}

Betriebsprüfung

img

img

Sie können sehen, dass Sie mit nur einer Zeile Funktionsanruf, können Sie leicht ein Diagramm zeichnen, und Sie können mehrere Arten von Diagrammen gleichzeitig anzeigen.

Vollständiger Quellcode der Strategie

Einstellungen der Parameter:img

Umsetzung des Quellcodes der Strategie:

var registerInfo = {}
var chart = null 
var arrCfg = []

function updateSeriesIdx() {
    var index = 0
    var map = {}
    _.each(arrCfg, function(cfg) {
        _.each(cfg.series, function(series) {
            var key = cfg.name + "|" + series.name
            map[key] = index
            index++
        })
    })

    for (var cfgName in registerInfo) {
        for (var i in registerInfo[cfgName].seriesIdxs) {
            var seriesName = registerInfo[cfgName].seriesIdxs[i].seriesName
            var key = cfgName + "|" + seriesName
            if (map[key]) {
                registerInfo[cfgName].seriesIdxs[i].index = map[key]
            }

            // Reset preBarTime of K-line data
            if (registerInfo[cfgName].seriesIdxs[i].type == "candlestick") {
                registerInfo[cfgName].seriesIdxs[i].preBarTime = 0
            } else if (registerInfo[cfgName].seriesIdxs[i].type == "line") {
                registerInfo[cfgName].seriesIdxs[i].preDotTime = 0
            } else if (registerInfo[cfgName].seriesIdxs[i].type == "flag") {
                registerInfo[cfgName].seriesIdxs[i].preFlagTime = 0
            }
        }
    }
    
    if (!chart) {
        chart = Chart(arrCfg)
    }
    chart.update(arrCfg)
    chart.reset()

    _G("registerInfo", registerInfo)
    _G("arrCfg", arrCfg)

    for (var cfgName in registerInfo) {
        for (var i in registerInfo[cfgName].seriesIdxs) {
            var buffer = registerInfo[cfgName].seriesIdxs[i].buffer            
            var index = registerInfo[cfgName].seriesIdxs[i].index
            if (buffer && buffer.length != 0 && registerInfo[cfgName].seriesIdxs[i].type == "line" && registerInfo[cfgName].seriesIdxs[i].preDotTime == 0) {                
                _.each(buffer, function(obj) {
                    chart.add(index, [obj.ts, obj.dot])
                    registerInfo[cfgName].seriesIdxs[i].preDotTime = obj.ts
                })
            } else if (buffer && buffer.length != 0 && registerInfo[cfgName].seriesIdxs[i].type == "flag" && registerInfo[cfgName].seriesIdxs[i].preFlagTime == 0) {
                _.each(buffer, function(obj) {
                    chart.add(index, obj.data)
                    registerInfo[cfgName].seriesIdxs[i].preFlagTime = obj.ts
                })
            }
        }
    }
}

function checkBufferLen(buffer, maxLen) {
    while (buffer.length > maxLen) {
        buffer.shift()
    }
}

$.PlotMultRecords = function(cfgName, seriesName, records, extension) {
    if (typeof(cfgName) == "undefined") {
        throw "need cfgName!"
    }

    var index = -1
    var eleIndex = -1

    do {
        var cfgInfo = registerInfo[cfgName]
        if (typeof(cfgInfo) == "undefined") {
            var cfg = {
                name : cfgName,
                __isStock: true,
                title : {
                    text: cfgName
                },
                tooltip: {
                    xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
                },
                legend: {
                    enabled: true,
                },
                plotOptions: {
                    candlestick: {
                        color: '#d75442',
                        upColor: '#6ba583'
                    }
                },
                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: 2,
                    inputEnabled: true
                },
                series: [{
                    type: 'candlestick',
                    name: seriesName,
                    id: seriesName,
                    data: []
                }],
            }    

            if (typeof(extension) != "undefined") {
                cfg.extension = extension
            }    

            registerInfo[cfgName] = {
                "cfgIdx" : arrCfg.length,                                                                               
                "seriesIdxs" : [{seriesName: seriesName, index: arrCfg.length, type: "candlestick", preBarTime: 0}],    
            }
            arrCfg.push(cfg)
            updateSeriesIdx()
        }    

        if (!chart) {
            chart = Chart(arrCfg)
        } else {
            chart.update(arrCfg)
        }

        _.each(registerInfo[cfgName].seriesIdxs, function(ele, i) {
            if (ele.seriesName == seriesName && ele.type == "candlestick") {
                index = ele.index
                eleIndex = i
            }
        })
        if (index == -1) {
            arrCfg[registerInfo[cfgName].cfgIdx].series.push({
                type: 'candlestick',
                name: seriesName,
                id: seriesName,
                data: []
            })
            registerInfo[cfgName].seriesIdxs.push({seriesName: seriesName, index: arrCfg.length, type: "candlestick", preBarTime: 0})
            updateSeriesIdx()
        }
    } while (index == -1)

    for (var i = 0 ; i < records.length ; i++) {
        if (records[i].Time == registerInfo[cfgName].seriesIdxs[eleIndex].preBarTime) {
            chart.add(index, [records[i].Time, records[i].Open, records[i].High, records[i].Low, records[i].Close], -1)
        } else if (records[i].Time > registerInfo[cfgName].seriesIdxs[eleIndex].preBarTime) {
            registerInfo[cfgName].seriesIdxs[eleIndex].preBarTime = records[i].Time
            chart.add(index, [records[i].Time, records[i].Open, records[i].High, records[i].Low, records[i].Close])
        }
    }
    
    return chart
}

$.PlotMultLine = function(cfgName, seriesName, dot, ts, extension) {
    if (typeof(cfgName) == "undefined") {
        throw "need cfgName!"
    }

    var index = -1
    var eleIndex = -1

    do {
        var cfgInfo = registerInfo[cfgName]
        if (typeof(cfgInfo) == "undefined") {
            var cfg = {
                name : cfgName,
                __isStock: true,
                title : {
                    text: cfgName
                },
                xAxis: {
                    type: 'datetime'
                },
                series: [{
                    type: 'line',
                    name: seriesName,
                    id: seriesName,
                    data: [],
                }]
            }    

            if (typeof(extension) != "undefined") {
                cfg.extension = extension
            }    

            registerInfo[cfgName] = {
                "cfgIdx" : arrCfg.length,
                "seriesIdxs" : [{seriesName: seriesName, index: arrCfg.length, type: "line", buffer: [], preDotTime: 0}], 
            }
            arrCfg.push(cfg)
            updateSeriesIdx()
        }    

        if (!chart) {
            chart = Chart(arrCfg)
        } else {
            chart.update(arrCfg)
        }

        _.each(registerInfo[cfgName].seriesIdxs, function(ele, i) {
            if (ele.seriesName == seriesName && ele.type == "line") {
                index = ele.index
                eleIndex = i
            }
        })
        if (index == -1) {
            arrCfg[registerInfo[cfgName].cfgIdx].series.push({
                type: 'line',
                name: seriesName,
                id: seriesName,
                data: [],
            })
            registerInfo[cfgName].seriesIdxs.push({seriesName: seriesName, index: arrCfg.length, type: "line", buffer: [], preDotTime: 0})
            updateSeriesIdx()
        }
    } while (index == -1)

    if (typeof(ts) == "undefined") {
        ts = new Date().getTime()
    }

    var buffer = registerInfo[cfgName].seriesIdxs[eleIndex].buffer
    if (registerInfo[cfgName].seriesIdxs[eleIndex].preDotTime != ts) {
        registerInfo[cfgName].seriesIdxs[eleIndex].preDotTime = ts
        chart.add(index, [ts, dot])
        buffer.push({ts: ts, dot: dot})       
        checkBufferLen(buffer, maxBufferLen)  
    } else {
        chart.add(index, [ts, dot], -1)
        buffer[buffer.length - 1].dot = dot   
    }

    return chart
}

$.PlotMultHLine = function(cfgName, value, label, color, style) {
    if (typeof(cfgName) == "undefined" || typeof(registerInfo[cfgName]) == "undefined") {
        throw "need cfgName!"
    }

    var cfg = arrCfg[registerInfo[cfgName].cfgIdx]
    if (typeof(cfg.yAxis) == "undefined") {
        cfg.yAxis = {
            plotLines: []
        }
    } else if (typeof(cfg.yAxis.plotLines) == "undefined") {
        cfg.yAxis.plotLines = []
    }

    var obj = {
        value: value,
        color: color || 'red',
        width: 2,
        dashStyle: style || 'Solid',
        label: {
            text: label || '',
            align: 'center'
        },
    }
    var found = false 
    for (var i = 0; i < cfg.yAxis.plotLines.length; i++) {
        if (cfg.yAxis.plotLines[i].label.text == label) {
            cfg.yAxis.plotLines[i] = obj
            found = true
        }
    }

    if (!found) {
        cfg.yAxis.plotLines.push(obj)
    }
    if (!chart) {
        chart = Chart(arrCfg)
    } else {
        chart.update(arrCfg)
    }

    return chart
}

$.PlotMultTitle = function(cfgName, title, chartTitle) {
    if (typeof(cfgName) == "undefined" || typeof(registerInfo[cfgName]) == "undefined") {
        throw "need cfgName!"
    }

    var cfg = arrCfg[registerInfo[cfgName].cfgIdx]

    cfg.subtitle = {
        text: title
    }

    if (typeof(chartTitle) !== 'undefined') {
        cfg.title = {
            text: chartTitle
        }
    }

    if (chart) {
        chart.update(arrCfg)
    }

    return chart
}

$.PlotMultFlag = function(cfgName, seriesName, ts, text, title, shape, color, onSeriesName) {
    if (typeof(cfgName) == "undefined" || typeof(registerInfo[cfgName]) == "undefined") {
        throw "need cfgName!"
    }

    var index = -1
    var eleIndex = -1

    do {
        if (!chart) {
            chart = Chart(arrCfg)
        } else {
            chart.update(arrCfg)
        }

        _.each(registerInfo[cfgName].seriesIdxs, function(ele, i) {
            if (ele.seriesName == seriesName && ele.type == "flag") {
                index = ele.index
                eleIndex = i
            }
        })
        if (index == -1) {
            arrCfg[registerInfo[cfgName].cfgIdx].series.push({
                type: 'flags',
                name: seriesName,
                onSeries: onSeriesName || arrCfg[registerInfo[cfgName].cfgIdx].series[0].id,
                data: []
            })
            registerInfo[cfgName].seriesIdxs.push({seriesName: seriesName, index: arrCfg.length, type: "flag", buffer: [], preFlagTime: 0})
            updateSeriesIdx()
        }
    } while(index == -1)
    
    if (typeof(ts) == "undefined") {
        ts = new Date().getTime()
    }

    var buffer = registerInfo[cfgName].seriesIdxs[eleIndex].buffer
    var obj = {x: ts, color: color, shape: shape, title: title, text: text}
    if (registerInfo[cfgName].seriesIdxs[eleIndex].preFlagTime != ts) {
        registerInfo[cfgName].seriesIdxs[eleIndex].preFlagTime = ts
        chart.add(index, obj)
        buffer.push({ts: ts, data: obj})
        checkBufferLen(buffer, maxBufferLen)
    } else {
        chart.add(index, obj, -1)
        buffer[buffer.length - 1].data = obj
    }

    return chart
}

$.GetArrCfg = function() {
    return arrCfg
}

function init() {
    if (isChartReset) {
        Log("Reset the chart", "#FF0000")
        chart = Chart(arrCfg)
        chart.reset()

        Log("Empty the persistent data, key:", "registerInfo、arrCfg #FF0000")
        _G("registerInfo", null)
        _G("arrCfg", null)
    } else {
        var multChartRegisterInfo = _G("registerInfo")
        var multChartArrCfg = _G("arrCfg")
        if (multChartRegisterInfo && multChartArrCfg) {
            registerInfo = multChartRegisterInfo
            arrCfg = multChartArrCfg
            Log("Recover registerInfo、arrCfg #FF0000")
        } else {
            Log("No data can be recovered #FF0000")
        }
    }
}

function onexit() {
    _G("registerInfo", registerInfo)
    _G("arrCfg", arrCfg)
    Log("Save data, key : registerInfo, arrCfg #FF0000")
}


// test
function main() {
    LogReset(10)
    var i = 0 
    var prePrintTs = 0

    while (true) {
        var r = exchange.GetRecords()
        var t = exchange.GetTicker()

        $.PlotMultRecords("chart1", "kline1", r, {layout: 'single', col: 6, height: '600px'})
        $.PlotMultRecords("chart2", "kline2", r, {layout: 'single', col: 6, height: '600px'})
        $.PlotMultLine("chart2", "line1", t.Last, r[r.length - 1].Time)
        $.PlotMultLine("chart3", "line2", t.Last)
        $.PlotMultLine("chart6", "line6", t.Time)
        $.PlotMultLine("chart4", "line3", t.Sell, new Date().getTime(), {layout: 'single', col: 4, height: '300px'})
        $.PlotMultLine("chart5", "line4", t.Volume, new Date().getTime(), {layout: 'single', col: 8, height: '300px'})       

        $.PlotMultHLine("chart1", r[r.length - 1].Close, "HLine1", "blue", "ShortDot")
        $.PlotMultHLine("chart4", t.Sell, "HLine2", "green")
        $.PlotMultTitle("chart3", "change : chart3->test1", "test1")

        var ts = new Date().getTime()
        if (ts - prePrintTs > 1000 * 20) {
            prePrintTs = ts 
            $.PlotMultFlag("chart3", "flag1", new Date().getTime(), "flag test", "flag1")
        }
        
        if (i == 10) {
            Log("i == 10")
            $.PlotMultFlag("chart4", "flag2", new Date().getTime(), "flag test", "flag2")
            $.PlotMultFlag("chart1", "flag3", new Date().getTime(), "flag test", "flag3", "squarepin", "green", "kline1")
        } else if (i == 20) {
            Log("i == 20")
            $.PlotMultLine("chart1", "line5", t.Last, r[r.length - 1].Time)
        } else if (i == 30) {
            Log("i == 30")
            $.PlotMultFlag("chart2", "flag4", new Date().getTime(), "flag test", "flag4", "circlepin", "black", "kline2")
        }
        
        Sleep(1000 * 5)
        i++
    }
}

Strategieadresse:https://www.fmz.com/strategy/353264

Wenn Sie interessiert sind, können Sie die unterstützten Diagrammtypen (wie Markttiefe-Diagramm, Balkendiagramm und Kuchendiagramm usw.) erhöhen und weiter aktualisieren.


Mehr