파이썬 버전의 간단한 그리드 전략

저자:리디아, 창작: 2022-12-23 21:00:45, 업데이트: 2023-09-20 11:17:48

img

파이썬 버전의 간단한 그리드 전략

전략 사각형에는 많은 파이썬 전략이 없습니다. 여기에 그리드 전략의 파이썬 버전이 작성되었습니다. 전략의 원리는 매우 간단합니다. 일련의 그리드 노드는 가격 범위 내에서 고정된 가격 거리에 의해 생성됩니다. 시장이 변경되고 가격이 그리드 노드 가격 위치에 도달하면 구매 주문이 제공됩니다. 주문이 종료되면 즉 미뤄진 주문의 가격과 이익 스프레드에 따라 판매 주문을 기다립니다. 설정된 가격 범위 내에서 변동을 캡처하십시오.

그리드 전략의 위험은 어떤 그리드 유형의 전략도 가격이 특정 범위 내에서 변동한다는 베팅이라는 것을 말할 필요도 없습니다. 가격이 그리드 범위를 벗어났을 때 심각한 부동 손실을 일으킬 수 있습니다. 따라서이 전략을 작성하는 목적은 파이썬 전략 작성 아이디어 또는 프로그램 설계에 대한 참조를 제공하는 것입니다.이 전략은 학습을 위해만 사용되며 실제 봇에서 위험 할 수 있습니다.

전략 아이디어에 대한 설명은 전략 코드 코멘트에서 직접 작성됩니다.

전략 코드

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

세 개의 테이블이 구성됩니다. 첫 번째 테이블은 현재 그리드 데이터 구조의 각 노드의 정보를 표시하고, 두 번째 테이블은 비정상적인 정보를 표시하고, 세 번째 테이블은 교환의 실제 목록 정보를 표시합니다.

백테스트

img img img

전략 주소

전략 주소

이 전략은 학습 및 백테스팅 목적으로만 사용되며, 관심있는 경우 최적화 및 업그레이드 될 수 있습니다.


관련

더 많은