0
focar em
48
Seguidores

SuperTrend V.1--Sistema de Super Trend Line

Criado em: 2020-04-20 22:10:36, atualizado em: 2024-12-12 21:03:30
comments   28
hits   11392

SuperTrend V.1–Sistema de Super Trend Line

1. Origem da história

Meu bom amigo Ran vem observando esse indicador há muito tempo e o recomendou a mim antes do Ano Novo para discutir se ele poderia ser convertido em uma forma quantitativa. Infelizmente, sofri de procrastinação e não o ajudei a realizar seu desejo até agora. Na verdade, meu entendimento de algoritmos fez um grande progresso recentemente. Pretendo escrever um tradutor de pinho um dia. Tudo pode ser python. . Ok, sem mais delongas, vamos apresentar esta lendária super tendência. .

2. Introdução ao sistema

Nova geração de sistema de negociação inteligente da CMC Markets - Supertrend Aqui está um artigo apresentando esse sistema. SuperTrend V.1–Sistema de Super Trend Line

Na nova geração do sistema de negociação inteligente da CMC Markets, selecione “Super Trend Line” nos indicadores técnicos para acessá-lo. Conforme mostrado na figura, você pode ajustar a “cor e a espessura” dos sinais ascendentes e descendentes de acordo com suas preferências. Então, o que é o indicador de supertendência? Antes de entender a fórmula do indicador supertrend, é necessário entender o ATR porque o supertrend usa valores de ATR para calcular os valores do indicador.

O algoritmo principal também é apresentado na imagem abaixo. SuperTrend V.1–Sistema de Super Trend Line

À primeira vista, a descrição principal é um canal de HL2 (preço médio da linha K) multiplicado por n vezes ATR. Crie uma nova tendência. Mas o artigo é bastante breve. Não há um algoritmo detalhado. Então pensei na melhor comunidade Tradingview. Não é de surpreender. Com certeza, está lá. SuperTrend V.1–Sistema de Super Trend Line

A julgar pelo gráfico, ele é bastante consistente com a tendência. Mas infelizmente é apenas um sinal de alerta.

3. Estude o código fonte

O código não parece muito longo, então vamos traduzi-lo e testá-lo. ! (っ•̀ω•́)っ✎⁾⁾! SuperTrend V.1–Sistema de Super Trend Line O código completo do pinheiro é como acima. .

4. Conversão de código

Aqui criamos uma nova estratégia no FMZ e a chamamos de SuperTrade SuperTrend V.1–Sistema de Super Trend Line

Em seguida, definimos dois parâmetros Factor e Pd SuperTrend V.1–Sistema de Super Trend Line

Para simplificar melhor a operação do código e torná-lo mais fácil de entender, precisamos usar o pacote de expansão de dados avançado do Pythonpandas

Durante o almoço, perguntei à professora Mengmeng se a FMZ apoia esta biblioteca. Verifiquei à tarde e realmente funcionou. A professora Mengmeng é realmente incrível.

1. Precisamos importar a biblioteca de tempo da biblioteca pandas 2. Configure o contrato trimestral na função principal (principalmente executando OKEX) 3. Defina um loop doTicker() para testar uma vez a cada 15 minutos. Execute o código em um ciclo de 15 minutos Em seguida, escrevemos a estratégia principal em doTicker().

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)
        

4. Precisamos recuperar o OHCLV da linha K, então use GetRecords() 5. Importamos os dados recuperados para o pandas M15 = pd.DataFrame(records) 6. Precisamos modificar a tag do cabeçalho da tabela. M15.colunas =[‘time’,‘open’,‘high’,‘low’,‘close’,‘volume’,‘OpenInterest’] Na verdade, ele apenas muda as primeiras letras de “open”, “high”, “low” e “close” para minúsculas, para que seja mais fácil escrever código mais tarde sem alternar entre maiúsculas e minúsculas.

def doTicker(records):
    M15 = pd.DataFrame(records)
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  

7. Adicione uma coluna hl2 ao conjunto de dados hl2=(high+low)/2

#HL2
M15['hl2']=(M15['high']+M15['low'])/2

8. Em seguida, vamos calcular o ATR Como o cálculo do ATR requer a importação de um comprimento variável, seu valor é Pd

Em seguida, nos referimos ao manual da linguagem Mai, e as etapas do algoritmo da média de volatilidade verdadeira do ATR são as seguintes: TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR : RMA(TR,N)

O valor TR é a maior das três diferenças a seguir. 1. A flutuação entre o preço mais alto e o preço mais baixo do dia de negociação atual MÁXIMA-MÍNIMA 2. A flutuação entre o preço de fechamento do dia de negociação anterior e o preço mais alto do dia de negociação atual (REF(CLOSE,1)-HIGH) 3. A flutuação entre o preço de fechamento do dia de negociação anterior e o preço mais baixo do dia de negociação atual (REF(CLOSE,1)-LOW) Então TR: MAX(MAX((ALTO-BAIXO),ABS(REF(FECHAR,1)-ALTO)),ABS(REF(FECHAR,1)-BAIXO));

Em cálculos Python

M15['prev_close']=M15['close'].shift(1)

Primeiro, configure um prev_close para obter os dados de close na linha anterior, ou seja, mova close para a direita em 1 grade para formar um novo parâmetro

ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]

Em seguida, defina uma variável intermediária para registrar a matriz de três valores de comparação de TR. (ALTO-BAIXO)(alto-anterior_fechamento)(baixo-anterior_fechamento)

M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)

Definimos uma nova coluna chamada TR no conjunto de dados. O valor de TR é o valor absoluto máximo da variável intermediária. Usamos as funções abs() e max().

    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

Por fim, precisamos calcular o valor de ATR, ATR:RMA (TR, N). Descobriu-se que o algoritmo RMA é, na verdade, uma variante de valor fixo do algoritmo EMA. N é a variável que importamos, onde o parâmetro padrão para ATR é 14. Aqui importamos alfa = o recíproco do comprimento.

===

Em seguida, use o algoritmo EWM para calcular a EMA O processo completo de cálculo do ATR é o seguinte

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

9 Comece a calcular Up e Dn

    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])

Up=hl2 -(Factor * atr) Dn=hl2 +(Factor * atr) Não é simples?

O seguinte é o segmento de código principal das linhas 15-21 na TV

TrendUp=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn

Trend = close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl = Trend==1? TrendUp: TrendDown

linecolor = Trend == 1 ? green : red

O objetivo principal deste parágrafo é expressar, Se em uma fase de alta, (linha inferior) TrendUp = max(Up,TrendUp[1]) Se estiver em fase de queda, (linha superior) TrendDown=min(Dn,TrendDown[1]) Ou seja, em uma tendência, o valor do ATR vem utilizando uma técnica similar à estratégia Bandit Bollinger. Continue estreitando o outro lado do canal

Aqui, cada cálculo de TrendUp e TrendDown precisa ser autoiterado. Ou seja, cada passo deve ser calculado com base no passo anterior. Então precisamos percorrer o conjunto de dados.

Aqui, primeiro precisamos criar novos campos TrendUp, TrendDown, Trend e linecolor para o conjunto de dados. E dê a eles um valor inicial Em seguida, use a sintaxe fillna(0) para preencher os dados com valores nulos nos resultados calculados anteriormente com 0

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

Iniciar um loop for Usando operações ternárias do Python em loops

    for x in range(len(M15)):

Calculando TrendUp TrendUp = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up O significado geral é que se o fechamento anterior > o TrendUp anterior, se for verdadeiro, pegue o valor máximo de Up e o TrendUp anterior, se não for verdadeiro, pegue o valor Up e passe para o TrendUp atual

        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]

Da mesma forma, calcule TrendDown TrendDown=min(Dn,TrendDown[-1]) if close[-1]

        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]

Abaixo está o sinalizador para calcular a direção do controle. Simplifiquei o pseudocódigo Trend= 1 if (close > TrendDown[-1]) else (x) x = -1 if (close< TrendUp[-1]) else Trend[-1]

O significado é que se o preço de fechamento > o TrendDown anterior, então pegue 1 (altista), caso contrário, pegue x Se o preço de fechamento for menor que o TrendUp anterior, então tome -1 (curto). Se não, tome o Trend anterior (o que significa que ele permanece inalterado). Traduzido em linguagem gráfica, significa romper o trilho superior para mudar a bandeira para alta, romper o trilho inferior para mudar a bandeira para baixa, e os outros tempos permanecem inalterados.

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]

Calcular Tsl e Linecolor Tsl= rendUp if (Trend==1) else TrendDown Tsl é usado para representar o valor do SuperTrend no gráfico. Isso significa que quando você estiver otimista, marque a faixa inferior no gráfico, e quando estiver pessimista, marque a faixa superior no gráfico. linecolor= ‘green’ if (Trend==1) else ‘red’ O significado de linecolor é se você estiver otimista, marque a linha verde, se estiver pessimista, marque a cor vazia (usado principalmente para exibição do Tradingview)

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'

As linhas 23 a 30 a seguir são principalmente para plotagem, o que não será explicado em detalhes aqui.

Por fim, existem 2 linhas de código para controle de sinal de compra e venda No Tradingview, significa dar um sinal após reverter a Bandeira. Converta instruções condicionais para python. Se a bandeira de tendência anterior mudar de -1 para 1, significa que a resistência superior foi quebrada. Abra longo Se a bandeira de tendência anterior mudar de 1 para -1, significa que o suporte descendente foi quebrado. Abra uma posição curta.

    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)

O código completo para esta seção é o seguinte:

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)
    
    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'
        
    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
        Log('Tsl=',Tsl)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)
        Log('Tsl=',Tsl)

SuperTrend V.1–Sistema de Super Trend Line

SuperTrend V.1–Sistema de Super Trend Line

5. Todos os códigos

Ajustei a estrutura geral do código. E mescle as instruções de ordens longas e curtas relacionadas à estratégia. Aqui está o código completo

'''backtest
start: 2019-05-01 00:00:00
end: 2020-04-21 00:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
'''

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)

       
def doTicker(records):
    #Log('onTick',exchange.GetTicker())
    M15 = pd.DataFrame(records)

    #Factor=3
    #Pd=7
    
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  
    
    #HL2
    M15['hl2']=(M15['high']+M15['low'])/2

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()


    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])
    
    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'Long' if ( M15['Trend'].values[x]==1) else  'Short'
 

    linecolor=M15['linecolor'].values[-2]
    close=M15['close'].values[-2]
    Tsl=M15['Tsl'].values[-2] 


    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):

        Log('SuperTrend V.1 Alert Long','Create Order Buy')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closesell")
            exchange.Buy(_C(exchange.GetTicker).Sell*1.01, Amount);
        
        exchange.SetDirection("buy")
        exchange.Buy(_C(exchange.GetTicker).Sell*1.01, vol);

    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long','Create Order Sell')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closebuy")
            exchange.Sell(_C(exchange.GetTicker).Buy*0.99,Amount);
        exchange.SetDirection("sell")
        exchange.Sell(_C(exchange.GetTicker).Buy*0.99, vol*2);

Link de estratégia pública: https://www.fmz.com/strategy/200625

6. Backtesting e Resumo

Selecionamos dados do ano passado para backtesting. Use o contrato trimestral da OKEX com um ciclo de 15 minutos. Os parâmetros definidos são, Factor=3 Pd=45 vol=100 (100 ingressos por pedido) O retorno anualizado é de aproximadamente 33%. Em geral, o recuo não é muito grande. A principal razão para isso é a falha do 312, que teve um impacto significativo no sistema. Se não houvesse 312, os retornos seriam melhores.

SuperTrend V.1–Sistema de Super Trend Line

6. Considerações finais

SuperTrend é um sistema de negociação muito bom

O princípio principal do sistema SuperTrend é usar a estratégia de rompimento do canal ATR (semelhante ao canal Kent) Mas a principal mudança está no uso da estratégia de estreitamento de Bandit Bollinger, ou princípio Donchian reverso. Os canais superior e inferior estão constantemente se estreitando durante a operação de mercado. Para conseguir a operação de avanço e rotação do canal. (Uma vez rompido o canal, os trilhos superiores e inferiores retornam aos seus valores iniciais)

Eu tracei o TrendUp TrendDn separadamente no TradingView Isso ajudará você a entender melhor essa estratégia Claro num piscar de olhos SuperTrend V.1–Sistema de Super Trend Line

Há também uma versão js no github. Não entendo muito bem de js, mas a julgar pela instrução if, parece haver algum problema. O endereço éhttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

Finalmente encontrei a versão original. Foi publicado em 2013.05.29 Escrito por Rajandran R Código C++ publicado no fórum Mt4https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4 Eu entendo aproximadamente o significado de C++ e vou reescrevê-lo quando tiver oportunidade.

Espero que todos possam aprender a essência disso. É difícil. ~!