Товарные фьючерсы Стратегия скользящей средней

Версия Python

Он полностью пересажен из «Стратегии скользящей средней CTP Commodity Futures Variety». Поскольку версия стратегии товарных фьючерсов на Python еще не имеет многовариантной стратегии, была портирована JavaScript-версия «CTP Commodity Futures Multi-Variable Moving Average Strategy». Предоставление некоторых дизайнерских идей и примеров многообразной стратегии товарных фьючерсов на Python. Независимо от версии JavaScript или версии Python, дизайн архитектуры стратегии берет свое начало от стратегии черепахи с несколькими разновидностями товарных фьючерсов.

Как простейшая стратегия, стратегия скользящей средней очень проста в освоении, потому что стратегия скользящей средней не имеет каких-либо продвинутых алгоритмов и сложной логики. Идеи ясны и просты, что позволяет новичкам больше сосредоточиться на изучении дизайна стратегии и даже удалить часть, связанную с кодированием, оставив многообразную структуру стратегии, которую можно легко расширить до ATR, MACD, BOLL и других индикаторных стратегий.

Исходный код стратегии

»’backtest
start: 2019-07-01 00:00:00
end: 2020-01-03 00:00:00
period: 1m
exchanges: [{«eid»:»OKEX»,»currency»:»BTC_USDT»}]
»’

import json

# Parameters
beginPrice = 5000 # Grid interval begin price
endPrice = 8000 # Grid interval end price
distance = 20 # Price distance of each grid node
pointProfit = 50 # Profit spread per grid node
amount = 0.01 # Number of pending orders per grid node
minBalance = 300 # Minimum fund balance of the account (at the time of purchase)

# Global variables
arrNet = []
arrMsg = []
acc = None

def findOrder (orderId, NumOfTimes, ordersList = []) :
for j in range(NumOfTimes) :
orders = None
if len(ordersList) == 0:
orders = _C(exchange.GetOrders)
else :
orders = ordersList
for i in range(len(orders)):
if orderId == orders[i][«Id»]:
return True
Sleep(1000)
return False

def cancelOrder (price, orderType) :
orders = _C(exchange.GetOrders)
for i in range(len(orders)) :
if price == orders[i][«Price»] and orderType == orders[i][«Type»]:
exchange.CancelOrder(orders[i][«Id»])
Sleep(500)

def checkOpenOrders (orders, ticker) :
global arrNet, arrMsg
for i in range(len(arrNet)) :
if not findOrder(arrNet[i][«id»], 1, orders) and arrNet[i][«state»] == «pending» :
orderId = exchange.Sell(arrNet[i][«coverPrice»], arrNet[i][«amount»], arrNet[i], ticker)
if orderId :
arrNet[i][«state»] = «cover»
arrNet[i][«id»] = orderId
else :
# Cancel
cancelOrder(arrNet[i][«coverPrice»], ORDER_TYPE_SELL)
arrMsg.append(«Pending order failed!» + json.dumps(arrNet[i]) + «, time:» + _D())

def checkCoverOrders (orders, ticker) :
global arrNet, arrMsg
for i in range(len(arrNet)) :
if not findOrder(arrNet[i][«id»], 1, orders) and arrNet[i][«state»] == «cover» :
arrNet[i][«id»] = -1
arrNet[i][«state»] = «idle»
Log(arrNet[i], «The node closes the position and resets to the idle state.», «#FF0000»)

def onTick () :
global arrNet, arrMsg, acc

ticker = _C(exchange.GetTicker) # Get the latest current ticker every time
for i in range(len(arrNet)): # Iterate through all grid nodes, find out the position where you need to pend a buy order according to the current market, and pend a buy order.
if i != len(arrNet) — 1 and arrNet[i][«state»] == «idle» and ticker.Sell > arrNet[i][«price»] and ticker.Sell < arrNet[i + 1][«price»]:
acc = _C(exchange.GetAccount)
if acc.Balance < minBalance : # If there is not enough money left, you can only jump out and do nothing.
arrMsg.append(«Insufficient funds» + json.dumps(acc) + «!» + «, time:» + _D())
break

orderId = exchange.Buy(arrNet[i][«price»], arrNet[i][«amount»], arrNet[i], ticker) # Pending buy orders
if orderId :
arrNet[i][«state»] = «pending» # Update the grid node status and other information if the buy order is successfully pending
arrNet[i][«id»] = orderId
else :
# Cancel h/the order
cancelOrder(arrNet[i][«price»], ORDER_TYPE_BUY) # Cancel orders by using the cancel function
arrMsg.append(«Pending order failed!» + json.dumps(arrNet[i]) + «, time:» + _D())
Sleep(1000)
orders = _C(exchange.GetOrders)
checkOpenOrders(orders, ticker) # Check the status of all buy orders and process them according to the changes.
Sleep(1000)
orders = _C(exchange.GetOrders)
checkCoverOrders(orders, ticker) # Check the status of all sell orders and process them according to the changes.

# The following information about the construction status bar can be found in the FMZ API documentation.
tbl = {
«type» : «table»,
«title» : «grid status»,
«cols» : [«node index», «details»],
«rows» : [],
}

for i in range(len(arrNet)) :
tbl[«rows»].append([i, json.dumps(arrNet[i])])

errTbl = {
«type» : «table»,
«title» : «record»,
«cols» : [«node index», «details»],
«rows» : [],
}

orderTbl = {
«type» : «table»,
«title» : «orders»,
«cols» : [«node index», «details»],
«rows» : [],
}

while len(arrMsg) > 20 :
arrMsg.pop(0)

for i in range(len(arrMsg)) :
errTbl[«rows»].append([i, json.dumps(arrMsg[i])])

for i in range(len(orders)) :
orderTbl[«rows»].append([i, json.dumps(orders[i])])

LogStatus(_D(), «\n», acc, «\n», «arrMsg length:», len(arrMsg), «\n», «`» + json.dumps([tbl, errTbl, orderTbl]) + «`»)

def main (): # Strategy execution starts here
global arrNet
for i in range(int((endPrice — beginPrice) / distance)): # The for loop constructs a data structure for the grid based on the parameters, a list that stores each grid node, with the following information for each grid node:
arrNet.append({
«price» : beginPrice + i * distance, # Price of the node
«amount» : amount, # Number of orders
«state» : «idle», # pending / cover / idle # Node Status
«coverPrice» : beginPrice + i * distance + pointProfit, # Node closing price
«id» : -1, # ID of the current order related to the node
})

while True: # After the grid data structure is constructed, enter the main strategy loop
onTick() # Processing functions on the main loop, the main processing logic
Sleep(500) # Control polling frequency

Стратегический адрес: https://www.fmz.com/strategy/208512

Сравнение бэктестов

Мы сравнили версию стратегии на JavaScript и версию стратегии на Python с бэктестом.

  • Бэктест версии Python

Мы используем публичный сервер для бэктеста, и мы видим, что бэктест версии Python немного быстрее.

  • Бэктест версии JavaScript

Видно, что результаты бэктеста точно такие же. Заинтересованные друзья могут углубиться в код, и будет не маленький выигрыш.

Расширение

Проведем демонстрацию расширения и распространим функцию графика на стратегию, как показано на рисунке:

В основном увеличьте часть кодирования:

  • Добавьте участника в класс Manager: objChart
  • Добавьте метод в класс Manager: PlotRecords

Некоторые другие изменения сделаны вокруг этих двух пунктов. Вы можете сравнить различия между двумя версиями и узнать идеи расширенных функций.

Версия стратегии скользящей средней на товарные фьючерсы на Python (расширенный график)

Источник