Type/to search
8
Follow
1363
Followers
Entwerfen einer Strichzeichnungsbibliothek mit mehreren Diagrammen
Discussions
Created 2022-03-31 11:28:35  Updated 2023-09-20 10:04:46
 2
 1945

img

Das Erstellen von Diagrammen und Zeichnen von Graphen wird häufig beim Schreiben und Entwerfen von Strategien verwendet. Für ein einzelnes benutzerdefiniertes Diagramm können wir verwendenStrichzeichnungsbibliothek(Studenten, die mit dem Konzept der Vorlagenbibliothek auf FMZ nicht vertraut sind, können die FMZ-API-Dokumentation lesen.) Dies ist für Zeichenvorgänge sehr praktisch. Diese Vorlagenbibliothek kann jedoch nicht die Anforderungen von Szenarien erfüllen, die mehrere Diagramme erfordern. Anschließend lernen wir die Gestaltungsideen dieser Strichzeichnungsbibliothek kennen und entwerfen darauf basierend eine Mehrdiagrammversion der Strichzeichnungsbibliothek.

Design-Exportfunktionen der „Vorlagenbibliothek“

Aufbauend auf dem Design der Exportfunktionen der „Line Drawing Library“ haben wir auch ähnliche Exportfunktionen für die Multi-Chart-Line Drawing Library entworfen.

  • $.PlotMultRecords
    Wird zum Zeichnen von K-Linien-Diagrammen verwendet, Parameterdesign: cfgName, seriesName, Datensätze, Erweiterung.
    cfgName: Der Name des Konfigurationsobjekts als separates Diagramm.
    seriesName: Der Name der aktuell darzustellenden K-Linien-Datenreihe.
    Datensätze: die eingehenden K-Line-Daten.
    Erweiterung: Konfigurationsinformationen zur Diagrammgröße, beispielsweise übergeben an:{layout: 'single', col: 6, height: '600px'}, d.h. das Diagramm mit dem Konfigurationsobjektnamen cfgName wird separat angezeigt, mit einer Breite von 6 und einer Höhe von 600px.

  • $.PlotMultLine
    Wird zum Zeichnen von Linien verwendet, Parameterdesign: cfgName, seriesName, dot, ts, extension
    cfgName: Der Name des Konfigurationsobjekts als separates Diagramm.
    seriesName: Der Name der zu zeichnenden Datenreihe.
    Punkt: Der vertikale Koordinatenwert des Punkts auf der zu zeichnenden Linie.
    ts: Zeitstempel, also der Wert auf der x-Zeitachse.
    Erweiterung: Konfigurationsinformationen zur Diagrammgröße.

  • $.PlotMultHLine
    Wird zum Zeichnen horizontaler Linien verwendet, Parameterdesign: cfgName, Wert, Beschriftung, Farbe, Stil
    cfgName: Name des Diagrammkonfigurationsobjekts.
    Wert: Der vertikale Koordinatenwert der horizontalen Linie.
    Bezeichnung: Der auf der horizontalen Linie angezeigte Text.
    Farbe: Die Farbe der Linie.
    Stil: Der Stil der Linie, zum Beispiel:Solid ShortDash ShortDot ShortDashDot ShortDashDotDot Dot Dash LongDash DashDot LongDashDot LongDashDotDot

  • $.PlotMultTitle
    Wird verwendet, um den Titel und Untertitel des Diagramms zu ändern. Parameterdesign: cfgName, Titel, Diagrammtitel
    cfgName: Name des Diagrammkonfigurationsobjekts.
    Titel: Untertitel.
    chartTitle: Diagrammtitel.

  • $.PlotMultFlag
    Zeichnen Sie ein kleines Flaggensymbol, Parameterdesign: cfgName, seriesName, ts, text, title, shape, color, onSeriesName
    cfgName: Name des Diagrammkonfigurationsobjekts.
    seriesName: Name der Datenreihe.
    ts: Zeitstempel
    Text: Der Text im kleinen Symbol.
    Titel: Der Titel des kleinen Symbols.
    Form: Die Form des kleinen Symbols.
    Farbe: Farbe des kleinen Symbols.
    onSeriesName: Basierend auf der angezeigten Datenreihe ist der Wert die ID der Datenreihe.

  • $.GetArrCfg
    Gibt ein Array von Diagrammkonfigurationsobjekten zurück.

Testfunktionsdesign

Zum besseren Verständnis habe ich Kommentare direkt zu den Testfunktionen geschrieben, um zu erklären, was jeder Funktionsaufruf bewirkt.

// test function main() { LogReset(10) var i = 0 var prePrintTs = 0 while (true) { var r = exchange.GetRecords() // 获取K线数据 var t = exchange.GetTicker() // 获取实时的tick数据 $.PlotMultRecords("chart1", "kline1", r, {layout: 'single', col: 6, height: '600px'}) // 创建一个名为chart1的K线图表,独立显示,宽度是6,高度是600px,K线数据系列名称为kline1,使用上面获取的r作为数据源画图 $.PlotMultRecords("chart2", "kline2", r, {layout: 'single', col: 6, height: '600px'}) // 创建第二个K线图表,名为chart2 $.PlotMultLine("chart2", "line1", t.Last, r[r.length - 1].Time) // 在K线图表即chart2上增加一条线,数据系列名称为line1,使用当前的tick数据的最新价Last作为线上的点的Y值。K线数据的最后一个BAR的时间戳作为X值 $.PlotMultLine("chart3", "line2", t.Last) // 创建一个只画线的图表,图表名称chart3,数据系列名称line2,使用实时tick数据的Last最新价格在当前时间(X值)画一个点(t.Last为Y值),注意图表不是独立显示 $.PlotMultLine("chart6", "line6", t.Time) // 创建一个只画线的图表chart6,注意图表不是独立显示,会和chart3在一起分页显示 $.PlotMultLine("chart4", "line3", t.Sell, new Date().getTime(), {layout: 'single', col: 4, height: '300px'}) // 创建一个只画线的图表chart4,独立显示,宽度4,高度300px $.PlotMultLine("chart5", "line4", t.Volume, new Date().getTime(), {layout: 'single', col: 8, height: '300px'}) // 创建一个只画线的图表chart5,独立显示,宽度8,高度300px $.PlotMultHLine("chart1", r[r.length - 1].Close, "HLine1", "blue", "ShortDot") // 给图表chart1增加水平横线 $.PlotMultHLine("chart4", t.Sell, "HLine2", "green") // 给图表chart4增加水平横线 $.PlotMultTitle("chart3", "change : chart3->test1", "test1") // 修改chart3的标题 var ts = new Date().getTime() if (ts - prePrintTs > 1000 * 20) { prePrintTs = ts // 触发时,给chart3图表上画小图标 $.PlotMultFlag("chart3", "flag1", new Date().getTime(), "flag test", "flag1") } if (i == 10) { Log("i == 10") // 触发时,给chart4,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") // 触发时,给chart1上添加一条线,但是只画了这条线的一个点,X坐标时间戳,Y坐标为t.Last值 $.PlotMultLine("chart1", "line5", t.Last, r[r.length - 1].Time) } else if (i == 30) { Log("i == 30") // 触发时,给chart2上画小图标 $.PlotMultFlag("chart2", "flag4", new Date().getTime(), "flag test", "flag4", "circlepin", "black", "kline2") } Sleep(1000 * 5) i++ } }

Ausführen von Tests

img

img

Sie sehen, dass Sie mit nur einer Zeile Funktionsaufrufen problemlos ein Diagramm zeichnen und mehrere Diagramme gleichzeitig anzeigen können.

Vollständiger Strategie-Quellcode

Parameterkonfiguration:
img

Implementierung des Quellcodes der Klassenbibliothek:

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) { _.each(arrCfg, function(cfg, cfgIdx) { if (cfg.name == cfgName) { registerInfo[cfgName].cfgIdx = cfgIdx } }) for (var i in registerInfo[cfgName].seriesIdxs) { var seriesName = registerInfo[cfgName].seriesIdxs[i].seriesName var key = cfgName + "|" + seriesName if (typeof(map[key]) != "undefined") { registerInfo[cfgName].seriesIdxs[i].index = map[key] } 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: { name: label || '', text: (label + ":" + value) || '', align: 'center' }, } var found = false for (var i = 0; i < cfg.yAxis.plotLines.length; i++) { if (cfg.yAxis.plotLines[i].label.name == 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 } $.removeChart = function(cfgName) { var index = -1 for (var i = 0; i < arrCfg.length; i++) { if (arrCfg[i].name == cfgName) { index = i break } } if (index != -1) { arrCfg.splice(index, 1) } if (typeof(registerInfo[cfgName]) != "undefined") { delete registerInfo[cfgName] } updateSeriesIdx() } function init() { if (isChartReset) { Log("重置图表", "#FF0000") chart = Chart(arrCfg) chart.reset() Log("清空持久化数据,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("恢复 registerInfo、arrCfg #FF0000") } else { Log("没有数据可以恢复 #FF0000") } } } function onexit() { _G("registerInfo", registerInfo) _G("arrCfg", arrCfg) Log("保存数据,key : registerInfo, arrCfg #FF0000") } // test function main() { LogReset(10) var i = 0 var prePrintTs = 0 var t = _C(exchange.GetTicker) while (true) { var r = _C(exchange.GetRecords) $.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", 10 + i) $.PlotMultLine("chart6", "line6", 100 + i) $.PlotMultLine("chart4", "line3", 1000 + i, new Date().getTime(), { layout: 'single', col: 4, height: '300px' }) $.PlotMultLine("chart5", "line4", 10000 + i, 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" + i, "flag1") } if (i == 10) { Log("i == 3") $.PlotMultFlag("chart4", "flag2", new Date().getTime(), "flag test" + i, "flag2") $.PlotMultFlag("chart1", "flag3", new Date().getTime(), "flag test" + i, "flag3", "squarepin", "green", "kline1") } else if (i == 20) { Log("i == 8") $.PlotMultLine("chart1", "line5", t.Last, r[r.length - 1].Time) } else if (i == 30) { Log("i == 10") $.PlotMultFlag("chart2", "flag4", new Date().getTime(), "flag test" + i, "flag4", "circlepin", "black", "kline2") $.removeChart("chart1") } i++ Sleep(1000 * 1) } }

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

Hier werfe ich nur ein paar Ideen in den Raum. Wenn Sie interessiert sind, können Sie weiterhin unterstützte Diagrammtypen hinzufügen und weiter aktualisieren, z. B. durch Zeichnen von Markttiefendiagrammen, Balkendiagrammen, Kreisdiagrammen usw.

Related Recommendations
Comment
All comments (2)

    梦大,超赞 [赞],图表名称如果用for遍历的变量代替,直接就会自动分页显示不同的表了。[呲牙]

    4 years ago

    是的,只要标题不同,就会分开显示了。不过要看模版导出函数传入的参数,可以指定叠加或者平铺。

    4 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)