avatar of 发明者量化-小小梦 发明者量化-小小梦
focar em Mensagem privada
4
focar em
1271
Seguidores

Use a função KLineChart para facilitar o desenho da estratégia

Criado em: 2022-07-01 15:54:06, atualizado em: 2023-09-18 20:11:05
comments   3
hits   2617

Use a função KLineChart para facilitar o desenho da estratégia

Use a função KLineChart para facilitar o desenho da estratégia

Ao projetar uma estratégia, muitas vezes é necessário projetar uma exibição de gráfico de estratégia ao usar JavaScript ou Python para escrever a estratégia. Usuários que não estão familiarizados com programação ou com a biblioteca de gráficos usada pela plataforma FMZ geralmente têm dificuldades com o design do código para desenhar em gráficos personalizados. Então, como podemos desenhar um gráfico de estratégia com conteúdo rico escrevendo apenas uma pequena quantidade de código?

Esse método de desenho simples, porém poderoso, pode ser visto na linguagem Pine, famosa por suas ricas funções de desenho. Se a interface de desenho da linguagem Pine puder ser conectada às estratégias das linguagens JavaScript e Python, isso facilitará muito aos desenvolvedores o design da função de desenho da estratégia. Com base nessa demanda, a plataforma FMZ atualizou a função de desenho personalizado e expandiu seu uso.KLineChartA função executa o desenho de gráficos personalizados. Você pode consultar a documentação da API: https://www.fmz.com/api#klinechart

Vamos usar JavaScript para escrever um exemplo simples para fazer uma transição.

Exemplo Simples

/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 30m
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

function main() {
    var c = KLineChart()
    while (true) {
        var bars = _C(exchange.GetRecords)
        for (var i = 0 ; i < bars.length ; i++) {
            var bar = bars[i]
            c.begin(bar)
            c.plot(bar.Volume, "volume")
            c.close()
        }
        Sleep(1000)
    }
}

Este exemplo é muito simples. Ele apenas desenha um gráfico de candlestick na área de desenho personalizada da estratégia, e desenha uma curva de volume correspondente a cada BAR de candlestick na posição do subgráfico do gráfico.

Use a função KLineChart para facilitar o desenho da estratégia

No código usamos primeirovar c = KLineChart()Crie um objeto de gráfico e então chame seus métodos para desenhar. Então, no loop, obtemos os dados da linha K (estrutura da matriz) e percorremos a matriz da linha K. Você pode usar um loop for simples para percorrer como no exemplo, ou pode usar outros métodos para percorrer.

As operações de desenho devem ser feitas a partir dec.begin(bar)A função inicia,c.close()A função termina.begincloseFunções são métodos do objeto gráfico c. Em seguida, use a função de desenho mais comumente usadaplotDesenhe a curva de volume em cada BARRA.

Um exemplo mais complexo

Suponha que queremos criar um gráfico com indicadores de Bollinger. Oh sim! Também é necessário anexar um gráfico de volume para cada BARRA, que pode ser desenhado assim:

/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

function main() {
    var c = KLineChart()

    // 策略主循环
    while(true) {
        // 轮询间隔
        Sleep(500)
        
        // 获取K线数据
        let bars = exchange.GetRecords()
        if (!bars || bars.length <= 20) {
            continue
        }
        
        // 计算布林指标
        var boll = TA.BOLL(bars)
        
        bars.forEach(function(bar, index) {
            c.begin(bar)
            // 画图操作
            c.plot(boll[0][index], "Boll_Up", {overlay: true})     // 画在图表主图
            c.plot(boll[1][index], "Boll_Mid", {overlay: true})    // 画在图表主图
            c.plot(boll[2][index], "Boll_Down", {overlay: true})   // 画在图表主图
            c.plot(bar.Volume, "volume")                           // 画在图表副图
            c.close()
        })
    
        // 策略交易逻辑
        // ...
        // ..
    }
}

Você pode ver no código que nossas informações de configuração de backtest na plataforma FMZ são:

/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

Esta configuração é testada usando o objeto de troca spot da Binance. Os resultados do teste são mostrados na figura:

Use a função KLineChart para facilitar o desenho da estratégia

Pode-se ver que usamos o método de desenho do Pine para simplificar bastante o código de desenho na linguagem JavaScript.

Escreva indicadores e outros dados para desenhar imagens

Operações como obtenção de dados da linha K e cálculo de indicadores são comuns e muito simples nos exemplos de estratégia e documentos de API do quadrado de estratégia da plataforma.

        // 获取K线数据
        let bars = exchange.GetRecords()
        if (!bars || bars.length <= 20) {   
            // 如果获取K线失败,即!bar为真则执行continue,忽略之后的代码,重新执行循环
            // 如果bars.length小于等于20,即K线BAR(柱)数量小于20,无法计算指标,也执行continue
            continue
        }
        
        // 计算布林指标
        var boll = TA.BOLL(bars)

Função de cálculo do indicador Bollinger TA.BOLL, se você não especificar os parâmetros do indicador Bollinger, os parâmetros padrão serão usadosBOLL(20, 2). O indicador Bollinger tem três linhas, então os dados retornados pela função TA.BOLL são uma matriz bidimensional. cápsula[0]、boll[1]、boll[2] são os três elementos da matriz boll, cada um dos quais representa uma linha e é uma matriz.

  • boll[0]: Bandas de Bollinger Online
  • boll[1]: Linha média das bandas de Bollinger
  • boll[2]: Bandas de Bollinger em baixa

Em seguida, veremos como desenhar o volume dos dados da linha K, ou seja, o volume de negociação, e os dados calculados do indicador Bollinger no gráfico.

Desenhamos os dados da linha K barra por barra, então precisamos percorrer todo o conjunto de linhas K, ou seja, percorrer o conjunto de barras no código. Aqui usamosforEachA travessia de métodos também pode ser percorrida usando o loop for.

        bars.forEach(function(bar, index) {
            c.begin(bar)
            // 画图操作
            c.plot(boll[0][index], "Boll_Up", {overlay: true})     // {overlay: true}参数控制,画在图表主图
            c.plot(boll[1][index], "Boll_Mid", {overlay: true})    // 画在图表主图
            c.plot(boll[2][index], "Boll_Down", {overlay: true})   // 画在图表主图
            c.plot(bar.Volume, "volume")                           // 画在图表副图
            c.close()
        })

Deve-se notar que cada vez que você começar a desenhar um gráfico em uma barra, você deve primeiroc.begin(bar)Chamadas de função,beginUma função é um método do nosso objeto gráfico c. Quando a operação de desenho estiver concluída, você precisa chamarc.close(). existirbeginFunções ecloseEntre as funções estão as funções de desenho que chamamos, que são semelhantes ao método de desenho da linguagem Pine. apoiar:barcolor bgcolor plot fill hline plotarrow plotshape plotchar plotcandle signal, você pode desenhar linhas, setas, marcar informações, etc. Os parâmetros dessas funções são consistentes com os parâmetros de função correspondentes da linguagem Pine, e as funções de desenho também são consistentes.

Adicionadas setas de sinal de negociação, marcadores, linhas horizontais e outros desenhos

Adicione algumas setas de sinal de negociação, marcadores e linhas horizontais ao exemplo de desenho do indicador Bollinger acima.

/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

function main() {
    var c = KLineChart()

    // 策略主循环
    while(true) {
        // 轮询间隔
        Sleep(500)
        
        // 获取K线数据
        let bars = exchange.GetRecords()
        if (!bars || bars.length <= 20) {
            continue
        }
        
        // 计算布林指标
        var boll = TA.BOLL(bars)
        
        bars.forEach(function(bar, index) {
            c.begin(bar)
            // 画图操作
            c.plot(boll[0][index], "Boll_Up", {overlay: true})     // 画在图表主图
            c.plot(boll[1][index], "Boll_Mid", {overlay: true})    // 画在图表主图
            c.plot(boll[2][index], "Boll_Down", {overlay: true})   // 画在图表主图
            c.plot(bar.Volume, "volume")                           // 画在图表副图
            
            c.hline(bar.Open, {overlay: true})                                         // 水平线
            c.plotarrow(bar.Close - bar.Open, {overlay: true})                         // 箭头
            c.plotshape(bar.Close - bar.Open > 0, {style: 'square', overlay: true})    // 画方块标记
            c.plotchar(bar.Close - bar.Open < 0, {char: '❄', size: "20px", overlay: true})           // 画出字符❄
            if (boll[0][index] && bar.Close > boll[0][index]) {
                c.signal("long", bar.Close, 1.5)
            } else if (boll[2][index] && bar.Close < boll[2][index]) {
                c.signal("closelong", bar.Close, 1.5)
            }
            
            c.close()
        })
    
        // 策略交易逻辑
        // ...
        // ..
    }
}

Use a função KLineChart para facilitar o desenho da estratégia

Como a operação de ordem da estratégia de linguagem Pine marcará automaticamente o sinal no gráfico,KLineChartO objeto gráfico criado pela função também é estendido com uma função para desenhar marcadores de sinal de compra e venda:c.signal

Objeto de configuração de gráfico

Você pode declarar uma estrutura para configurar o estilo do gráfico. Por exemplo, a variável chartCfg a seguir representa as informações de configuração de uma linha de grade.

    var chartCfg = {
        grid: {
            show: true,
            // 网格水平线
            horizontal: {
                show: true,
                size: 2,
                color: '#FF0000',    // 水平网格线的颜色
                // 'solid'|'dash'
                style: 'dash',       // 线的类型
                dashValue: [2, 2]
            },
   	        // 网格垂直线
            vertical: {
                show: true,
                size: 2,
                color: '#32CD32',
                // 'solid'|'dash'
                style: 'solid',
                dashValue: [2, 2]
            }
        },
    }

O objeto de configuração do gráfico é uma estrutura de dados que define algumas propriedades e a aparência do gráfico. Por exemplo, o exemplo usa uma configuração de estilo de linha de grade. Existem também muitas opções que podem ser configuradas e modificadas, como as configurações relacionadas do eixo X e do eixo Y, as configurações da linha do cursor, as configurações das informações do prompt, as configurações do estilo do indicador técnico, o configurações do estilo BAR da linha K, etc.

Claro, se você não estiver familiarizado com eles,KLineChartA função não precisa passar um objeto de configuração de gráfico ao criar um objeto de gráfico. O gráfico criado é do estilo padrão. Usando as funções da API da plataforma FMZKLineChartFunção para criar objeto gráfico:

var c = KLineChart(chartCfg)

Código de teste para desenhar linhas de grade:

/*backtest
start: 2022-03-21 09:00:00
end: 2022-06-21 15:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

function main() {
    var chartCfg = {
        grid: {
            show: true,
            // 网格水平线
            horizontal: {
                show: true,
                size: 2,
                color: '#FF0000',
                // 'solid'|'dash'
                style: 'dash',
                dashValue: [2, 2]
            },
   	        // 网格垂直线
            vertical: {
                show: true,
                size: 2,
                color: '#32CD32',
                // 'solid'|'dash'
                style: 'solid',
                dashValue: [2, 2]
            }
        },
    }

    var c = KLineChart(chartCfg)

    // 策略主循环
    while(true) {
        // 轮询间隔
        Sleep(500)
        
        // 获取K线数据
        var bars = _C(exchange.GetRecords)
        bars.forEach(function(bar, index) {
            c.begin(bar)
            c.close()
        })
    
        // 策略交易逻辑
        // ...
        // ..
    }
}

Use a função KLineChart para facilitar o desenho da estratégia

Exemplo de estilo de configuração de gráfico

Pode ser usado para referenciar as configurações do estilo de configuração do gráfico.

{
    // 网格线
    grid: {
        show: true,
        // 网格水平线
        horizontal: {
            show: true,
            size: 1,
            color: '#393939',
            // 'solid'|'dash'
            style: 'dash',
            dashValue: [2, 2]
        },
        // 网格垂直线
        vertical: {
            show: false,
            size: 1,
            color: '#393939',
            // 'solid'|'dash'
            style: 'dash',
            dashValue: [2, 2]
        }
    },
    // 蜡烛图
    candle: {
        // 蜡烛图上下间距,大于1为绝对值,大于0小余1则为比例
        margin: {
            top: 0.2,
            bottom: 0.1
        },
        // 蜡烛图类型 'candle_solid'|'candle_stroke'|'candle_up_stroke'|'candle_down_stroke'|'ohlc'|'area'
        type: 'candle_solid',
        // 蜡烛柱
        bar: {
            upColor: '#26A69A',
            downColor: '#EF5350',
            noChangeColor: '#888888'
        },
        // 面积图
        area: {
            lineSize: 2,
            lineColor: '#2196F3',
            value: 'close',
            backgroundColor: [{
                offset: 0,
                color: 'rgba(33, 150, 243, 0.01)'
            }, {
                offset: 1,
                color: 'rgba(33, 150, 243, 0.2)'
            }]
        },
        priceMark: {
            show: true,
            // 最高价标记
            high: {
                show: true,
                color: '#D9D9D9',
                textMargin: 5,
                textSize: 10,
                textFamily: 'Helvetica Neue',
                textWeight: 'normal'
            },
            // 最低价标记
            low: {
                show: true,
                color: '#D9D9D9',
                textMargin: 5,
                textSize: 10,
                textFamily: 'Helvetica Neue',
                textWeight: 'normal',
            },
            // 最新价标记
            last: {
                show: true,
                upColor: '#26A69A',
                downColor: '#EF5350',
                noChangeColor: '#888888',
                line: {
                    show: true,
                    // 'solid'|'dash'
                    style: 'dash',
                    dashValue: [4, 4],
                    size: 1
                },
                text: {
                    show: true,
                    size: 12,
                    paddingLeft: 2,
                    paddingTop: 2,
                    paddingRight: 2,
                    paddingBottom: 2,
                    color: '#FFFFFF',
                    family: 'Helvetica Neue',
                    weight: 'normal',
                    borderRadius: 2
                }
            }
        },
        // 提示
        tooltip: {
            // 'always' | 'follow_cross' | 'none'
            showRule: 'always',
            // 'standard' | 'rect'
            showType: 'standard',
            labels: ['时间', '开', '收', '高', '低', '成交量'],
            values: null,
            defaultValue: 'n/a',
            rect: {
                paddingLeft: 0,
                paddingRight: 0,
                paddingTop: 0,
                paddingBottom: 6,
                offsetLeft: 8,
                offsetTop: 8,
                offsetRight: 8,
                borderRadius: 4,
                borderSize: 1,
                borderColor: '#3f4254',
                backgroundColor: 'rgba(17, 17, 17, .3)'
            },
            text: {
                size: 12,
                family: 'Helvetica Neue',
                weight: 'normal',
                color: '#D9D9D9',
                marginLeft: 8,
                marginTop: 6,
                marginRight: 8,
                marginBottom: 0
            }
        }
    },
    // 技术指标
    technicalIndicator: {
        margin: {
            top: 0.2,
            bottom: 0.1
        },
        bar: {
            upColor: '#26A69A',
            downColor: '#EF5350',
            noChangeColor: '#888888'
        },
        line: {
            size: 1,
            colors: ['#FF9600', '#9D65C9', '#2196F3', '#E11D74', '#01C5C4']
        },
        circle: {
            upColor: '#26A69A',
            downColor: '#EF5350',
            noChangeColor: '#888888'
        },
        // 最新值标记
        lastValueMark: {
            show: false,
            text: {
                show: false,
                color: '#ffffff',
                size: 12,
                family: 'Helvetica Neue',
                weight: 'normal',
                paddingLeft: 3,
                paddingTop: 2,
                paddingRight: 3,
                paddingBottom: 2,
                borderRadius: 2
            }
        },
        // 提示
        tooltip: {
            // 'always' | 'follow_cross' | 'none'
            showRule: 'always',
            // 'standard' | 'rect'
            showType: 'standard',
            showName: true,
            showParams: true,
            defaultValue: 'n/a',
            text: {
                size: 12,
                family: 'Helvetica Neue',
                weight: 'normal',
                color: '#D9D9D9',
                marginTop: 6,
                marginRight: 8,
                marginBottom: 0,
                marginLeft: 8
            }
        }
    },
    // x轴
    xAxis: {
        show: true,
        height: null,
        // x轴线
        axisLine: {
            show: true,
            color: '#888888',
            size: 1
        },
        // x轴分割文字
        tickText: {
            show: true,
            color: '#D9D9D9',
            family: 'Helvetica Neue',
            weight: 'normal',
            size: 12,
            paddingTop: 3,
            paddingBottom: 6
        },
        // x轴分割线
        tickLine: {
            show: true,
            size: 1,
            length: 3,
            color: '#888888'
        }
    },
    // y轴
    yAxis: {
        show: true,
        width: null,
        // 'left' | 'right'
        position: 'right',
        // 'normal' | 'percentage' | 'log'
        type: 'normal',
        inside: false,
        reverse: false,
        // y轴线
        axisLine: {
            show: true,
            color: '#888888',
            size: 1
        },
        // y轴分割文字
        tickText: {
            show: true,
            color: '#D9D9D9',
            family: 'Helvetica Neue',
            weight: 'normal',
            size: 12,
            paddingLeft: 3,
            paddingRight: 6
        },
        // y轴分割线
        tickLine: {
            show: true,
            size: 1,
            length: 3,
            color: '#888888'
        }
    },
    // 图表之间的分割线
    separator: {
        size: 1,
        color: '#888888',
        fill: true,
        activeBackgroundColor: 'rgba(230, 230, 230, .15)'
    },
    // 十字光标
    crosshair: {
        show: true,
        // 十字光标水平线及文字
        horizontal: {
            show: true,
            line: {
                show: true,
                // 'solid'|'dash'
                style: 'dash',
                dashValue: [4, 2],
                size: 1,
                color: '#888888'
            },
            text: {
                show: true,
                color: '#D9D9D9',
                size: 12,
                family: 'Helvetica Neue',
                weight: 'normal',
                paddingLeft: 2,
                paddingRight: 2,
                paddingTop: 2,
                paddingBottom: 2,
                borderSize: 1,
                borderColor: '#505050',
                borderRadius: 2,
                backgroundColor: '#505050'
            }
        },
        // 十字光标垂直线及文字
        vertical: {
            show: true,
            line: {
                show: true,
                // 'solid'|'dash'
                style: 'dash',
                dashValue: [4, 2],
                size: 1,
                color: '#888888'
            },
            text: {
                show: true,
                color: '#D9D9D9',
                size: 12,
                family: 'Helvetica Neue',
                weight: 'normal',
                paddingLeft: 2,
                paddingRight: 2,
                paddingTop: 2,
                paddingBottom: 2,
                borderSize: 1,
                borderColor: '#505050',
                borderRadius: 2,
                backgroundColor: '#505050'
            }
        }
    },
    // 图形
    shape: {
        point: {
            backgroundColor: '#2196F3',
            borderColor: '#2196F3',
            borderSize: 1,
            radius: 4,
            activeBackgroundColor: '#2196F3',
            activeBorderColor: '#2196F3',
            activeBorderSize: 1,
            activeRadius: 6
        },
        line: {
            // 'solid'|'dash'
            style: 'solid'
            color: '#2196F3',
            size: 1,
            dashValue: [2, 2]
        },
        polygon: {
            // 'stroke'|'fill'
            style: 'stroke',
            stroke: {
                // 'solid'|'dash'
                style: 'solid',
                size: 1,
                color: '#2196F3',
                dashValue: [2, 2]
            },
            fill: {
                color: 'rgba(33, 150, 243, 0.1)'
            }
        },
        arc: {
            // 'stroke'|'fill'
            style: 'stroke',
            stroke: {
                // 'solid'|'dash'
                style: 'solid',
                size: 1,
                color: '#2196F3',
                dashValue: [2, 2]
            },
            fill: {
                color: '#2196F3'
            }
        },
        text: {
            style: 'fill',
            color: '#2196F3',
            size: 12,
            family: 'Helvetica Neue',
            weight: 'normal',
            offset: [0, 0]
        }
    },
    annotation: {
        // 'top' | 'bottom' | 'point'
        position: 'top',
        offset: [20, 0]
        symbol: {
            // 'diamond' | 'circle' | 'rect' | 'triangle' | 'custom' | 'none'
            type: 'diamond',
            size: 8,
            color: '#2196F3',
            activeSize: 10,
            activeColor: '#FF9600'
        }
    },
    tag: {
        // 'top' | 'bottom' | 'point'
        position: 'point',
        offset: 0,
        line: {
            show: true,
            style: LineStyle.DASH,
            dashValue: [4, 2],
            size: 1,
            color: '#2196F3'
        },
        text: {
            color: '#FFFFFF',
            backgroundColor: '#2196F3',
            size: 12,
            family: 'Helvetica Neue',
            weight: 'normal',
            paddingLeft: 2,
            paddingRight: 2,
            paddingTop: 2,
            paddingBottom: 2,
            borderRadius: 2,
            borderSize: 1,
            borderColor: '#2196F3'
        },
        mark: {
            offset: 0,
            color: '#FFFFFF',
            backgroundColor: '#2196F3',
            size: 12,
            family: 'Helvetica Neue',
            weight: 'normal',
            paddingLeft: 2,
            paddingRight: 2,
            paddingTop: 2,
            paddingBottom: 2,
            borderRadius: 2,
            borderSize: 1,
            borderColor: '#2196F3'
        }
    }
}

Isso não facilita o desenho e o design da estratégia?