
En el artículo anterior se implementó una estrategia de Python muy simple:「Versión Python de la estrategia de perseguir al alza y vender a la baja」Esta estrategia permite operar una cuenta para realizar operaciones programadas en un determinado par de divisas. El principio es muy simple: perseguir las subidas y vender las bajadas. A veces queremos utilizar la misma lógica comercial para operar diferentes pares comerciales. Puede crear varios robots y configurar diferentes pares comerciales para operar con varias monedas. Si la estrategia no es muy complicada, dada la poderosa flexibilidad de la plataforma de comercio cuantitativo del inventor. Es muy fácil transformar una estrategia en una estrategia multiproducto, de modo que puedas ejecutar múltiples pares comerciales simplemente creando un robot.
El código fuente de la estrategia transformada:
'''backtest
start: 2019-02-20 00:00:00
end: 2020-01-10 00:00:00
period: 1m
exchanges: [{"eid":"OKEX","currency":"BTC_USDT"},{"eid":"OKEX","currency":"ETH_USDT","stocks":30},{"eid":"OKEX","currency":"LTC_USDT","stocks":100}]
'''
import time
import json
params = {
"arrBasePrice": [-1, -1, -1], # -1
"arrRatio": [0.05, 0.05, 0.05], # 0.05
"arrAcc": [], # _C(exchange.GetAccount)
"arrLastCancelAll": [0, 0, 0], # 0
"arrMinStocks": [0.01, 0.01, 0.01], # 0.01
"arrPricePrecision": [2, 2, 2], # 2
"arrAmountPrecision": [3, 2, 2], # 2
"arrTick":[]
}
def CancelAll(e):
while True :
orders = _C(e.GetOrders)
for i in range(len(orders)) :
e.CancelOrder(orders[i]["Id"], orders[i])
if len(orders) == 0 :
break
Sleep(1000)
def process(e, index):
global params
ticker = _C(e.GetTicker)
params["arrTick"][index] = ticker
if params["arrBasePrice"][index] == -1 :
params["arrBasePrice"][index] = ticker.Last
if ticker.Last - params["arrBasePrice"][index] > 0 and (ticker.Last - params["arrBasePrice"][index]) / params["arrBasePrice"][index] > params["arrRatio"][index]:
params["arrAcc"][index] = _C(e.GetAccount)
if params["arrAcc"][index].Balance * params["arrRatio"][index] / ticker.Last > params["arrMinStocks"][index]:
e.Buy(ticker.Last, params["arrAcc"][index].Balance * params["arrRatio"][index] / ticker.Last)
params["arrBasePrice"][index] = ticker.Last
if ticker.Last - params["arrBasePrice"][index] < 0 and (params["arrBasePrice"][index] - ticker.Last) / params["arrBasePrice"][index] > params["arrRatio"][index]:
params["arrAcc"][index] = _C(e.GetAccount)
if params["arrAcc"][index].Stocks * params["arrRatio"][index] > params["arrMinStocks"][index]:
e.Sell(ticker.Last, params["arrAcc"][index].Stocks * params["arrRatio"][index])
params["arrBasePrice"][index] = ticker.Last
ts = time.time()
if ts - params["arrLastCancelAll"][index] > 60 * 5 :
CancelAll(e)
params["arrLastCancelAll"][index] = ts
def main():
global params
for i in range(len(exchanges)) :
params["arrAcc"].append(_C(exchanges[i].GetAccount))
params["arrTick"].append(_C(exchanges[i].GetTicker))
exchanges[i].SetPrecision(params["arrPricePrecision"][i], params["arrAmountPrecision"][i])
for key in params :
if len(params[key]) < len(exchanges):
raise "params error!"
while True:
tblAcc = {
"type" : "table",
"title": "account",
"cols": ["账户信息"],
"rows": []
}
tblTick = {
"type" : "table",
"title": "ticker",
"cols": ["行情信息"],
"rows": []
}
for i in range(len(exchanges)):
process(exchanges[i], i)
for i in range(len(exchanges)):
tblAcc["rows"].append([json.dumps(params["arrAcc"][i])])
tblTick["rows"].append([json.dumps(params["arrTick"][i])])
LogStatus(_D(), "\n`" + json.dumps([tblAcc, tblTick]) + "`")
Sleep(500)
¿Compara el código y descubre que es muy diferente del código del artículo anterior? De hecho, la lógica de negociación es exactamente la misma, sin cambios. Es solo que hemos cambiado la estrategia a múltiples variedades, por lo que no podemos usar la forma anterior de “variable única como parámetro de estrategia”. Una solución más razonable es Para crear el parámetro Array, el índice de cada posición en el array corresponde al par comercial agregado.

Luego encapsule el código de lógica de transacción en una funciónprocessEn el bucle principal de la estrategia, esta función se llama iterativamente de acuerdo con los pares comerciales agregados, de modo que el código de lógica comercial se ejecuta una vez para cada par comercial.
for i in range(len(exchanges)):
process(exchanges[i], i)
params = {
"arrBasePrice": [-1, -1, -1], # -1
"arrRatio": [0.05, 0.05, 0.05], # 0.05
"arrAcc": [], # _C(exchange.GetAccount)
"arrLastCancelAll": [0, 0, 0], # 0
"arrMinStocks": [0.01, 0.01, 0.01], # 0.01
"arrPricePrecision": [2, 2, 2], # 2
"arrAmountPrecision": [3, 2, 2], # 2
"arrTick":[]
}
Este diseño permite que cada par comercial tenga sus propios parámetros, porque los precios de cada par comercial pueden variar mucho y los parámetros también pueden diferir, por lo que a veces se requieren configuraciones diferenciadas.
Puede comparar los cambios de esta función. Esta función simplemente modifica un poco de código y luego piensa en la intención de esta modificación.
Se agregaron gráficos para mostrar datos de mercado y datos de activos de la cuenta en la barra de estado, de modo que los activos y datos de mercado correspondientes a cada objeto de intercambio se puedan mostrar en tiempo real.
Después de dominar las ideas de diseño anteriores, ¿no es muy fácil modificar una estrategia de Python para convertirla en una estrategia multivariante?



La estrategia es solo de referencia, para realizar pruebas retrospectivas y pruebas. Si te interesa, puedes optimizarla y actualizarla. Dirección de la política