策略広場には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
# 参数
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) # 控制轮询频率
格子データ構造を比較して,この格子データ構造を比較して,GetOrders
インターフェイスが返した現在の挂注リスト. 挂注された注文の変更を分析する (取引または否),グリッドデータ構造を更新し,フォローアップを行う. そして,挂注された注文は,取引が完了するまで撤回されません. 価格偏差であっても撤回されません. デジタル通貨市場にはしばしばプラグがあるため,これらの挂注は,プラグを受け取る可能性のある単位の場合もあります.
戦略データを可視化し,利用するLogStatus
機能は,状態バーでデータをリアルタイムに表示します.
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" : [],
}
3つの表が構築され,最初の表は現在の格子データ構造の各ノードに関する情報を示し,第2表は異常情報を示し,第3表は取引所が実際に掲示した情報を示します.
この戦略は,学習,復習テスト,アップグレードの最適化に関心のある人のための参照のみです.
千年老いた松鼠#請求を撤回 cancelOrder ((arrNet[i]["price", ORDER_TYPE_BUY) # 撤回関数を使用して撤回する この価格でインデックスで注文をキャンセルする方法は? fmzのAPIではIDのみが表示されています. OK取引所の現在のドキュメントではIDまたはカスタムIDのみです.
ぶっ飛ばす素晴らしい!
千年老いた松鼠おっと,デフを見ました. すみません.
発明者 量化 - 微かな夢この cancelOrder は exchange ではなく,CancelOrder です.これは私が設定した関数です.