Phương pháp lưới đơn giản của Python

Tác giả:Giấc mơ nhỏ, Tạo: 2020-01-04 14:28:04, Cập nhật: 2023-10-17 21:27:38

img

Phương pháp lưới đơn giản của Python

Không có nhiều chiến lược Python trên quảng trường chiến lược, đây là một chiến lược lưới phiên bản Python. Các nguyên tắc chiến lược rất đơn giản, tạo ra một loạt các nút lưới với khoảng cách giá cố định trong một khoảng giá, khi giá đạt đến vị trí giá của một nút lưới, khi thay đổi thị trường, đặt hàng mua sẽ được treo.

Không cần phải nói nhiều về rủi ro của chiến lược lưới, bất kỳ loại chiến lược lưới nào cũng thuộc về sự biến động của giá trong một phạm vi nào đó, một khi giá vượt ra khỏi phạm vi lưới, có thể gây ra sự nổi lên nghiêm trọng. Vì vậy, mục đích của việc viết chiến lược này là để cung cấp tham khảo về ý tưởng viết hoặc thiết kế chương trình của Python. Chiến lược này chỉ được sử dụng để học, thực tế có thể có nhiều rủi ro.

Những ý tưởng chiến lược được giải thích trực tiếp trong chú thích mã chiến lược.

Mã chiến lược

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

# 参数
beginPrice = 5000   # 网格区间开始价格
endPrice = 8000     # 网格区间结束价格
distance = 20       # 每个网格节点的价格距离
pointProfit = 50    # 每个网格节点的利润差价
amount = 0.01       # 每个网格节点的挂单量
minBalance = 300    # 账户最小资金余额(买入时)

# 全局变量
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 :
                # 撤销
                cancelOrder(arrNet[i]["coverPrice"], ORDER_TYPE_SELL)
                arrMsg.append("挂单失败!" + 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], "节点平仓,重置为空闲状态。", "#FF0000")


def onTick () :
    global arrNet, arrMsg, acc

    ticker = _C(exchange.GetTicker)    # 每次获取当前最新的行情
    for i in range(len(arrNet)):       # 遍历所有网格节点,根据当前行情,找出需要挂单的位置,挂买单。
        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 :     # 如果钱不够了,只能跳出,什么都不做了。
                arrMsg.append("资金不足" + json.dumps(acc) + "!" + ", time:" + _D())
                break

            orderId = exchange.Buy(arrNet[i]["price"], arrNet[i]["amount"], arrNet[i], ticker) # 挂买单
            if orderId : 
                arrNet[i]["state"] = "pending"   # 如果买单挂单成功,更新网格节点状态等信息
                arrNet[i]["id"] = orderId
            else :
                # 撤单
                cancelOrder(arrNet[i]["price"], ORDER_TYPE_BUY)    # 使用撤单函数撤单
                arrMsg.append("挂单失败!" + json.dumps(arrNet[i]) + ", time:" + _D())
    Sleep(1000)
    orders = _C(exchange.GetOrders)    
    checkOpenOrders(orders, ticker)    # 检测所有买单的状态,根据变化做出处理。
    Sleep(1000)
    orders = _C(exchange.GetOrders)    
    checkCoverOrders(orders, ticker)   # 检测所有卖单的状态,根据变化做出处理。

    # 以下为构造状态栏信息,可以查看FMZ API 文档。
    tbl = {
        "type" : "table", 
        "title" : "网格状态",
        "cols" : ["节点索引", "详细信息"], 
        "rows" : [], 
    }    

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

    errTbl = {
        "type" : "table", 
        "title" : "记录",
        "cols" : ["节点索引", "详细信息"], 
        "rows" : [], 
    }

    orderTbl = {
     	"type" : "table", 
        "title" : "orders",
        "cols" : ["节点索引", "详细信息"], 
        "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 ():         # 策略执行从这里开始
    global arrNet
    for i in range(int((endPrice - beginPrice) / distance)):        # for 这个循环根据参数构造了网格的数据结构,是一个列表,储存每个网格节点,每个网格节点的信息如下:
        arrNet.append({
            "price" : beginPrice + i * distance,                    # 该节点的价格
            "amount" : amount,                                      # 订单数量
            "state" : "idle",    # pending / cover / idle           # 节点状态
            "coverPrice" : beginPrice + i * distance + pointProfit, # 节点平仓价格
            "id" : -1,                                              # 节点当前相关的订单的ID
        })
        
    while True:    # 构造好网格数据结构后,进入策略主要循环
        onTick()   # 主循环上的处理函数,主要处理逻辑
        Sleep(500) # 控制轮询频率

Ý tưởng thiết kế chính của chiến lược là so sánh các cấu trúc dữ liệu lưới mà bạn duy trì với các cấu trúc dữ liệu của các hệ thống khác nhau.GetOrdersGiao diện trả về danh sách các đơn đặt hàng hiện tại. Phân tích thay đổi của các đơn đặt hàng được treo (có giao dịch hay không), cập nhật cấu trúc dữ liệu lưới, thực hiện các thao tác tiếp theo. Và các đơn đặt hàng được treo sẽ không bị hủy cho đến khi giao dịch được thực hiện, ngay cả khi giá đi ngược lại, vì thị trường tiền kỹ thuật số thường có các nút, các đơn đặt hàng này cũng có thể nhận được các nút (nếu giao dịch có giới hạn số lượng tất cả các đơn đặt hàng được treo, điều đó sẽ được điều chỉnh).

Dữ liệu chiến lược được hiển thị, sử dụngLogStatusChức năng hiển thị dữ liệu trong thời gian thực trên thanh trạng thái.

    tbl = {
        "type" : "table", 
        "title" : "网格状态",
        "cols" : ["节点索引", "详细信息"], 
        "rows" : [], 
    }    

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

    errTbl = {
        "type" : "table", 
        "title" : "记录",
        "cols" : ["节点索引", "详细信息"], 
        "rows" : [], 
    }

    orderTbl = {
     	"type" : "table", 
        "title" : "orders",
        "cols" : ["节点索引", "详细信息"], 
        "rows" : [],    
    }

Ba bảng được xây dựng, bảng đầu tiên hiển thị thông tin về từng nút trong cấu trúc dữ liệu lưới hiện tại, bảng thứ hai hiển thị thông tin bất thường, bảng thứ ba hiển thị thông tin đăng ký thực tế của sàn giao dịch.

Kiểm tra lại

img

img

Địa chỉ chiến lược

Địa chỉ chiến lược

Các chiến lược chỉ dành cho tham khảo học tập, thử nghiệm kiểm tra lại, có thể tối ưu hóa nâng cấp.


Có liên quan

Thêm nữa

Con sóc tuổi ngàn năm# Thu hồi cancelOrder ((arrNet[i]["price], ORDER_TYPE_BUY) # Sử dụng chức năng hủy bỏ Phương tiện này được sử dụng để hủy lệnh với giá chỉ mục gì? chỉ hiển thị id trong API của fmz, OK giao dịch tài liệu hiện tại chỉ có id hoặc tùy chỉnh id...

đùaĐúng rồi!

Con sóc tuổi ngàn nămTôi thấy Def ở trên, xin lỗi, xin lỗi.

Giấc mơ nhỏCancelOrder, đó là chức năng mà tôi đã định nghĩa.