En este artículo se analizan dos soluciones. La otra solución, que se encuentra al final del artículo, es más sencilla (recomendada).
Muchos desarrolladores que usan Python para escribir estrategias desean almacenar los archivos de código de estrategia localmente, pero les preocupa la seguridad de las estrategias. ComoFMZ API
Una solución propuesta en el documento:
Seguridad de la política Desarrolle estrategias en la plataforma de negociación cuantitativa de Inventor. Las estrategias solo son visibles para los titulares de cuentas de Inventor Quantitative. Además, el código de estrategia se puede localizar completamente en la plataforma de negociación cuantitativa de Inventor. Por ejemplo, la estrategia se puede encapsular en un paquete Python y cargar en el código de estrategia, logrando así la localización de la estrategia. https://www.fmz.com/api#%E7%AD%96%E7%95%A5%E5%AE%89%E5%85%A8%E6%80%A7
De hecho, no hay necesidad de preocuparse por esto, pero como existe tal solución, se proporciona un ejemplo de implementación completo.
Encontremos una estrategia de Python simple para demostrar, usando el clásicoDual Thrust
Estrategia, dirección de estrategia: https://www.fmz.com/strategy/21856
Nos esforzamos por no cambiar ninguna parte del código de la estrategia y encapsulamos la estrategia en un archivo que pueda ser invocado por el código de la estrategia en la plataforma FMZ. El resultado de la ejecución es exactamente el mismo que el de ejecutar la estrategia directamente. El mayor problema con la encapsulación es que los objetos globales, las funciones globales y los valores constantes llamados por el código de estrategia en la plataforma FMZ no se pueden acceder en nuestros archivos encapsulados, por lo que debemos encontrar una manera de pasar estos objetos, funciones, variables. , y constantes al documento encapsulado. Luego lo manejaremos paso a paso.
Pegue en el archivo testA abierto en el 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
La función principal del código anterior es declarar las funciones y variables globales utilizadas en el archivo actual. Luego reserve la interfaz para importar estas funciones.SetExchanges
,SetParams
,SetFunc
. Las estrategias en la plataforma FMZ llaman a estas funciones y transmiten algunas funciones, objetos, etc. utilizados.
La estrategia de puesta en marcha es muy sencilla, como sigue:
En la plataforma FMZ solo hay unas pocas líneas de código escritas. Cabe señalar que los parámetros de esta estrategia de inicio son los mismos que los de nuestra estrategia encapsulada.Versión Python de futuros de OKCoin de doble empujeEs exactamente lo mismo. De hecho, puedes copiar directamente la estrategia “Versión Python de Dual Thrust OKCoin Futures”, luego borrar el código de la estrategia y pegarlo.
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()
De esta manera, encapsulamos el cuerpo lógico de la política en el archivo testA y lo colocamos localmente en el dispositivo del host. En la plataforma FMZ, solo necesitamos guardar una política de inicio. El robot que crea esta política de inicio puede cargar directamente nuestro archivo local. y ejecutarlo localmente en el host.
Cargue directamente el archivo para su ejecución. En esta ocasión preparamos un archivo testB para colocar el código de la estrategia “Versión Python de 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': {
...
La estrategia es demasiado larga, por lo que se omite y no es necesario cambiar el código de estrategia en absoluto. Luego prepare la “Versión Python de Dual Thrust OKCoin Futures (inicie la estrategia y ejecute el archivo testB directamente)”, que es nuestra estrategia en la plataforma FMZ, cree un robot, cargue el archivo testB directamente y ejecútelo directamente. Se debe tener en cuenta que la estrategia de inicio también debe tener la misma configuración de parámetros de estrategia (parámetros de interfaz de estrategia) que la versión original de “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 realizar una prueba retrospectiva:
Los resultados del backtest son consistentes con las pruebas anteriores.
Obviamente, el segundo método mencionado anteriormente es más sencillo y recomendable. Si hay un método mejor, no dude en dejar un mensaje.