Este artigo discute duas soluções. A outra solução no final do artigo é mais simples (recomendada).
Muitos desenvolvedores que usam Python para escrever estratégias querem armazenar os arquivos de código de estratégia localmente, mas estão preocupados com a segurança das estratégias. ComoFMZ API
Uma solução proposta no documento:
Segurança de Política Desenvolva estratégias na Inventor Quantitative Trading Platform. As estratégias são visíveis apenas para os titulares de contas Inventor Quantitative. Além disso, o código da estratégia pode ser totalmente localizado na Inventor Quantitative Trading Platform. Por exemplo, a estratégia pode ser encapsulada em um pacote Python e carregada no código da estratégia, alcançando assim a localização da estratégia. https://www.fmz.com/api#%E7%AD%96%E7%95%A5%E5%AE%89%E5%85%A8%E6%80%A7
Na verdade, não há necessidade de se preocupar com isso, mas como existe essa solução, um exemplo completo de implementação é fornecido.
Vamos encontrar uma estratégia Python simples para demonstrar, usando o clássicoDual Thrust
Estratégia, endereço de estratégia: https://www.fmz.com/strategy/21856
Nós nos esforçamos para não mudar nenhuma parte do código da estratégia e encapsulamos a estratégia em um arquivo que pode ser chamado pelo código da estratégia na plataforma FMZ. O resultado da execução é exatamente o mesmo que executar a estratégia diretamente. O maior problema com o encapsulamento é que os objetos globais, funções globais e valores constantes chamados pelo código de estratégia na plataforma FMZ não podem ser acessados em nossos arquivos encapsulados, então devemos encontrar uma maneira de passar esses objetos, funções, variáveis , e constantes para o documento encapsulado. Então, cuidaremos disso passo a passo.
Cole no arquivo testA aberto no editor local.
# 函数、对象
exchanges = None
exchange = None
Log = None
Sleep = None
TA = None
Chart = None
LogProfitReset = None
LogStatus = None
_N = None
_C = None
LogProfit = None
# 策略参数
ContractTypeIdx = None
MarginLevelIdx = None
NPeriod = None
Ks = None
Kx = None
AmountOP = None
Interval = None
LoopInterval = None
PeriodShow = None
# 常量
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 principal função do código acima é declarar as funções e variáveis globais usadas no arquivo atual. Em seguida, reserve a interface para importar essas funçõesSetExchanges
,SetParams
,SetFunc
. As estratégias na plataforma FMZ chamam essas funções e passam algumas funções, objetos, etc. usados.
A estratégia de inicialização é muito simples, como segue:
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 os mesmos da nossa estratégia encapsulada.Versão Python do Dual Thrust OKCoin FuturesÉ exatamente o mesmo. Na verdade, você pode copiar diretamente a estratégia “versão Python do Dual Thrust OKCoin Futures”, depois limpar o código da estratégia e colá-lo
import sys
# 这里我写的是自己放置testA文件的路径,具体我替换为xxx了,简单说就是设置自己的testA文件路径就可以了
sys.path.append("/Users/xxx/Desktop/pythonPlayground/")
import testA
def main():
# 传递交易所对象
testA.SetExchanges(exchanges)
# 传递全局函数 SetFunc(pLog, pSleep, pTA, pChart, pLogStatus, pLogProfitReset, p_N, p_C, pLogProfit)
testA.SetFunc(Log, Sleep, TA, Chart, LogStatus, LogProfitReset, _N, _C, LogProfit)
# 传递策略参数 SetParams(pContractTypeIdx, pMarginLevelIdx, pNPeriod, pKs, pKx, pAmountOP, pInterval, pLoopInterval, pPeriodShow)
testA.SetParams(ContractTypeIdx, MarginLevelIdx, NPeriod, Ks, Kx, AmountOP, Interval, LoopInterval, PeriodShow)
# 执行封装的testA文件中的策略主函数
testA.main()
Dessa forma, encapsulamos o corpo da lógica da política no arquivo testA e o colocamos localmente no dispositivo do host. Na plataforma FMZ, precisamos salvar apenas uma política de inicialização. O robô que cria essa política de inicialização pode carregar diretamente nosso arquivo local e executá-lo localmente no host. .
Carregue o arquivo diretamente para execução. Desta vez, preparamos um arquivo testB para colocar o código da estratégia “versão Python do Dual Thrust OKCoin Futures”.
import time
class Error_noSupport(BaseException):
def __init__(self):
Log("只支持OKCoin期货!#FF0000")
class Error_AtBeginHasPosition(BaseException):
def __init__(self):
Log("启动时有期货持仓! #FF0000")
ChartCfg = {
'__isStock': True,
'title': {
'text': 'Dual Thrust 上下轨图'
},
'yAxis': {
...
A estratégia é muito longa, por isso é omitida, e o código da estratégia não precisa ser alterado. Em seguida, prepare a “versão Python do Dual Thrust OKCoin Futures (inicie a estratégia e execute o arquivo testB diretamente)”, que é nossa estratégia na plataforma FMZ, crie um robô, carregue diretamente o arquivo testB e execute-o diretamente. Vale ressaltar que a estratégia de inicialização também deve ter as mesmas configurações de parâmetros de estratégia (parâmetros de interface de estratégia) que a versão original do “Python version Dual Thrust OKCoin Futures”.
if __name__ == '__main__':
Log("run...")
try:
# 文件路径做了处理,可以写入自己testB文件放置的实际路径
f = open("/Users/xxx/Desktop/pythonPlayground/testB.py", "r")
code = f.read()
exec(code)
except Exception as e:
Log(e)
Para executar um backtest:
Os resultados do backtest são consistentes com os testes acima.
Obviamente, o segundo método acima é mais simples e recomendado. Se houver um método melhor, você é bem-vindo para deixar uma mensagem.