Python バージョンのシンプルなグリッド戦略

作者: リン・ハーンリディア, 作成日:2022-12-23 21:00:45, 更新日:2023-09-20 11:17:48

img

Python バージョンのシンプルなグリッド戦略

ストラテジースクエアには多くのPython戦略はない.ここでグリッド戦略のPythonバージョンが書かれています. 戦略の原理は非常にシンプルです. グリッドノードは価格範囲内の固定価格距離によって生成されます. 市場が変化し,価格がグリッドノード価格位置に達すると,購入オーダーが表示されます. 注文が閉ざされると,つまり,待機中のオーダーの価格プラス利益の差に応じて,ポジションを閉じるために販売オーダーを待機します. 設定された価格範囲内の変動をキャプチャーします.

グリッド戦略のリスクは,グリッド型戦略は,価格が一定の範囲内で変動するという賭けである.価格がグリッド範囲を突破すると,深刻な浮動損失を引き起こす可能性があることは言うまでもありません.したがって,この戦略を書く目的は,Python戦略の書き込みアイデアやプログラム設計のための参照を提供することです.この戦略は学習のためにのみ使用され,実際のボットではリスクが高い可能性があります.

戦略アイデアの説明は 戦略コードのコメントに直接書かれています

戦略コード

'''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

戦略の主なデザインのアイデアは,現在待機中の注文のリストを比較することです.GetOrdersネットワークデータ構造によって操作する. 待機中の注文の変更を分析し (閉ざされているか否か),グリッドデータ構造を更新し,次の操作を行います. さらに,待機中の注文は,取引が完了するまでキャンセルされません.価格が逸脱したとしても,デジタル通貨市場はしばしばピンの状況があるため,これらの待機中の注文はピンの注文も受けることができます (取引所で待機中の注文の数が制限されている場合,調整されます).

戦略データ可視化にはLogStatus状態バーにデータをリアルタイムで表示する機能

    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" : [],    
    }

3つの表が構築される.最初の表は,現在のグリッドデータ構造の各ノードの情報を表示し,第2表は異常情報を表示し,第3表は,交換の実際のリスト情報を示します.

バックテスト

img img img

戦略アドレス

戦略アドレス

戦略は学習とバックテスト目的のみで, 興味がある場合は最適化およびアップグレードすることができます.


関連性

もっと