Ensinar a encapsular uma estratégia Python em um arquivo local

Autora:Bem-estar, Criado: 2020-07-09 10:21:31, Atualizado: 2023-10-28 15:28:00

img

Muitos desenvolvedores que escrevem estratégias em Python querem colocar os arquivos de código de estratégia localmente, preocupando-se com a segurança da estratégia.

Segurança estratégica

A estratégia é desenvolvida na plataforma FMZ, e a estratégia é visível apenas para os titulares de contas FMZ. E na plataforma FMZ, o código da estratégia pode ser completamente localizado, por exemplo, a estratégia é encapsulada em um pacote Python e carregada no código da estratégia, de modo que a localização da estratégia seja realizada.

Para mais informações, acesse:https://www.fmz.com/api

De facto, esse tipo de preocupação não é necessário, mas, uma vez que existem tais necessidades, daremos um exemplo completo de aplicação.

Encapsular uma estratégia

Vamos encontrar uma estratégia Python simples para demonstração, usando o clássicoDual Thrustestratégia, endereço da estratégia:https://www.fmz.com/strategy/21856Nós nos esforçamos para não alterar qualquer parte do código da estratégia, encapsular a estratégia em um arquivo que pode ser chamado pelo código da estratégia na plataforma FMZ, e o resultado da execução é exatamente o mesmo que executar a estratégia diretamente. O maior problema com a encapsulamento é que os objetos globais, funções globais e valores constantes chamados pelo código da estratégia na plataforma FMZ não podem ser acessados nos arquivos que encapsulamos, então devemos encontrar uma maneira de passar esses objetos, funções, variáveis e constantes para o arquivo encapsulado. vamos fazer passo a passo.

img

Coloque no arquivotestAfoi aberta pelo editor local.

img

Adicionar algum código, e manter a parte de código estratégia copiado e colado intacto

# Function, object
exchanges = None
exchange = None
Log = None
Sleep = None
TA = None
Chart = None
LogProfitReset = None
LogStatus = None
_N = None
_C = None 
LogProfit = None  


# Strategy parameters
ContractTypeIdx = None
MarginLevelIdx = None
NPeriod = None
Ks = None
Kx = None
AmountOP = None
Interval = None
LoopInterval = None
PeriodShow = None  

# constant
ORDER_STATE_PENDING = 0
ORDER_STATE_CLOSED = 1
ORDER_STATE_CANCELED = 2
ORDER_STATE_UNKNOWN = 3
ORDER_TYPE_BUY = 0 
ORDER_TYPE_SELL = 1
PD_LONG = 0
PD_SHORT = 1  


def SetExchanges(es):
    global exchanges, exchange
    exchanges = es
    exchange = es[0]  

def SetFunc(pLog, pSleep, pTA, pChart, pLogStatus, pLogProfitReset, p_N, p_C, pLogProfit):
    global Log, Sleep, TA, Chart, LogStatus, LogProfitReset, _N, _C, LogProfit
    Log = pLog
    Sleep = pSleep
    TA = pTA
    Chart = pChart
    LogStatus = pLogStatus
    LogProfitReset = pLogProfitReset
    _N = p_N
    _C = p_C
    LogProfit = pLogProfit  

def SetParams(pContractTypeIdx, pMarginLevelIdx, pNPeriod, pKs, pKx, pAmountOP, pInterval, pLoopInterval, pPeriodShow):
    global ContractTypeIdx, MarginLevelIdx, NPeriod, Ks, Kx, AmountOP, Interval, LoopInterval, PeriodShow
    ContractTypeIdx = pContractTypeIdx
    MarginLevelIdx = pMarginLevelIdx
    NPeriod = pNPeriod
    Ks = pKs
    Kx = pKx
    AmountOP = pAmountOP
    Interval = pInterval
    LoopInterval = pLoopInterval
    PeriodShow = pPeriodShow

A função principal do código acima é declarar as funções globais e variáveis usadas no arquivo atual.SetExchanges, SetParams, SetFuncAs estratégias na plataforma FMZ chamam essas funções e passam algumas funções e objetos usados.

Estratégia de arranque na plataforma FMZ

A estratégia de arranque é muito simples, da seguinte forma:

img

Há apenas algumas linhas de código escritas na plataforma FMZ. Deve-se notar que os parâmetros desta estratégia de inicialização são exatamente os mesmos que a nossa estratégia embaladaVersão Python do código de estratégia de futuros OKCoin Dual ThrustNa verdade, você pode copiar diretamenteVersão Python do código de estratégia de futuros OKCoin Dual ThrustEstratégia, depois limpa o código da estratégia, pega-o.

import sys
# Here I wrote the path where I put the testA file myself. I replaced it with xxx. To put it simply, I set the path of my testA file.
sys.path.append("/Users/xxx/Desktop/pythonPlayground/")
import testA

def main():
    # Passing Exchange Object
    testA.SetExchanges(exchanges)
    # Pass global function SetFunc(pLog, pSleep, pTA, pChart, pLogStatus, pLogProfitReset, p_N, p_C, pLogProfit)
    testA.SetFunc(Log, Sleep, TA, Chart, LogStatus, LogProfitReset, _N, _C, LogProfit)
    # Passing strategy parameters SetParams(pContractTypeIdx, pMarginLevelIdx, pNPeriod, pKs, pKx, pAmountOP, pInterval, pLoopInterval, pPeriodShow)
    testA.SetParams(ContractTypeIdx, MarginLevelIdx, NPeriod, Ks, Kx, AmountOP, Interval, LoopInterval, PeriodShow)
    # Execute the main strategy function in the encapsulated testA file
    testA.main()

Deste modo, encapsulamos o corpo principal da lógica estratégica natestANo FMZ, só precisamos salvar uma estratégia de inicialização. O robô que cria essa estratégia de inicialização pode carregar diretamente nosso arquivo local e executá-lo localmente.

Comparação de testes de retrospectiva

  • CargatestAarquivo local para backtest

img

  • Estratégia original, backtesting no servidor público

img

Outra maneira mais simples

Carregue o arquivo diretamente para execução. Desta vez preparamos umtestBFicheiro com o código para oVersão Python do código de estratégia de futuros OKCoin Dual Thrust strategy.

import time
class Error_noSupport(BaseException):
    def __init__(self):
        Log("Only OKCoin futures are supported!#FF0000")

class Error_AtBeginHasPosition(BaseException):
    def __init__(self):
        Log("There is a futures position at startup!#FF0000")

ChartCfg = {
    '__isStock': True,
    'title': {
        'text': 'Dual Thrust Top and bottom rail map'
    },
    'yAxis': {

...

Se a estratégia for demasiado longa, é omitida e o código de estratégia não precisa de ser alterado.

Então, prepare-se.Versão Python do código de estratégia de futuros OKCoin Dual Thrust(iniciar estratégia, executar directamentetestBFicheiro), que é a nossa estratégia na plataforma FMZ, criar um robô, carregar diretamente otestBFicheiro, e executá-lo diretamente. Deve-se notar que a estratégia de inicialização também deve ter exatamente as mesmas configurações de parâmetros de estratégia (parâmetros de interface de estratégia) que a versão original deVersão Python do código de estratégia de futuros OKCoin Dual Thrust.

img

if __name__ == '__main__':
    Log("run...")
    try:
        # The file path is processed, you can write the actual path of your testB file
        f = open("/Users/xxx/Desktop/pythonPlayground/testB.py", "r")
        code = f.read()
        exec(code)
    except Exception as e:
        Log(e)

Realizar um backtest:

img

O resultado do backtest é consistente com o teste anterior.

Obviamente, o segundo método acima é mais simples, é recomendado usar.


Mais.