最近越來越多的TradingView使用者,把TradingView圖表信號連通到發明者量化平臺(FMZ.COM)上根據圖表信號,讓FMZ上的機器人策略執行交易,這樣對於編程技術小白來說省去了大量代碼編寫、設計工作。直接可以讓指標用於程序化、自動化交易,降低了不少程序化、量化交易開發門檻。對於TradingViewWebHook實現實盤自動交易,有好幾種設計方案。
之前的方案,走的是發明者量化交易平臺擴展API接口,給機器人發送指令。今天我們一起來看另一種方案,讓TradingView的報警WebHook請求直接發送給FMZ量化交易平臺機器人,實現直接發送指令,命令機器人交易。
機器人策略源碼
策略使用Python
編寫,在使用該策略創建機器人並啓動後,機器人會創建一個線程,該線程會啓動一個服務監聽設置的端口。等待外部請求並處理。我測試的時候是用在服務器上的託管者測試的,託管者所在設備必須能被外部訪問。機器人執行交易時,使用的是市價單接口,當然也可以改造這個策略,實現限價單下單邏輯。爲了簡單易懂、程序精簡,這裏使用了市價單,所以必須交易所支持市價單纔行。
'''
請求格式:http://x.x.x.x:xxxx/data?access_key=xxx&secret_key=yyy&type=buy&amount=0.001
策略機器人蔘數:
- 類型:加密字符串,AccessKey , SecretKey ,可以用FMZ平臺的低權限的API KEY,或者自己生成KEY也可以。
- 類型:字符串,合約ID,ContractType
- 類型:數值,端口號,Port
'''
import _thread
import json
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
from urllib.parse import parse_qs, urlparse
def url2Dict(url):
query = urlparse(url).query
params = parse_qs(query)
result = {key: params[key][0] for key in params}
return result
class Executor(BaseHTTPRequestHandler):
def do_GET(self):
try:
dictParam = url2Dict(self.path)
Log("測試", dictParam)
except Exception as e:
Log("Provider do_GET error, e:", e)
def do_POST(self):
try:
self.send_response(200)
self.send_header("Content-type", "application/json")
self.end_headers()
dictParam = url2Dict(self.path)
# 校驗
if len(dictParam) == 4 and dictParam["access_key"] == AccessKey and dictParam["secret_key"] == SecretKey:
del dictParam["access_key"]
del dictParam["secret_key"]
Log("接收到請求", "參數:", dictParam, "#FF0000")
'''
map[access_key:xxx amount:0.001 secret_key:yyy type:buy]
'''
isSpot = True
if exchange.GetName().find("Futures") != -1:
if ContractType != "":
exchange.SetContractType(ContractType)
isSpot = False
else :
raise "未設置期貨合約"
if isSpot and dictParam["type"] == "buy":
exchange.Buy(-1, float(dictParam["amount"]))
Log(exchange.GetAccount())
elif isSpot and dictParam["type"] == "sell":
exchange.Sell(-1, float(dictParam["amount"]))
Log(exchange.GetAccount())
elif not isSpot and dictParam["type"] == "long":
exchange.SetDirection("buy")
exchange.Buy(-1, float(dictParam["amount"]))
Log("持倉:", exchange.GetPosition())
elif not isSpot and dictParam["type"] == "short":
exchange.SetDirection("sell")
exchange.Sell(-1, float(dictParam["amount"]))
Log("持倉:", exchange.GetPosition())
elif not isSpot and dictParam["type"] == "cover_long":
exchange.SetDirection("closebuy")
exchange.Sell(-1, float(dictParam["amount"]))
Log("持倉:", exchange.GetPosition())
elif not isSpot and dictParam["type"] == "cover_short":
exchange.SetDirection("closesell")
exchange.Buy(-1, float(dictParam["amount"]))
Log("持倉:", exchange.GetPosition())
# 寫入數據應答
self.wfile.write(json.dumps({"state": "ok"}).encode())
except Exception as e:
Log("Provider do_POST error, e:", e)
def createServer(host):
try:
server = ThreadingHTTPServer(host, Executor)
Log("Starting server, listen at: %s:%s" % host)
server.serve_forever()
except Exception as e:
Log("createServer error, e:", e)
raise Exception("stop")
def main():
# 開啓一個線程
try:
_thread.start_new_thread(createServer, (("0.0.0.0", Port), )) # VPS服務器上測試
except Exception as e:
Log("錯誤信息:", e)
raise Exception("stop")
Log("賬戶資產信息:", _C(exchange.GetAccount))
while True:
if exchange.GetName() == "Futures_CTP":
if exchange.IO("status"):
LogStatus(_D(), "CTP連接")
else:
LogStatus(_D(), "CTP未連接")
else:
LogStatus(_D())
Sleep(2000)
策略參數:
TradingView的WebHook報警請求
報警請求設置爲:
http://xxx.xxx.xxx.xxx:80/data?access_key=e3809e173e23004821a9bfb6a468e308&secret_key=45a811e0009d91ad21154e79d4074bc6&type=sell&amount=0.1
由於Trading View
發送的是POST
請求,所以監聽服務中要監聽POST
請求,並且Trading View
對於http
協議只允許用80端口。
xxx.xxx.xxx.xxx
,爲機器人所在託管者的設備IP地址。填寫自己的設備具體IP地址,需要注意必須能被外網訪問纔行。access_key
,secret_key
可以自己生成,只要WebHook
報警請求中的access_key
,secret_key
填寫與機器人蔘數上配置的一致即可。type
,交易方向,買入或者賣出、開倉或者平倉,注意現貨期貨是區分的。如果是期貨,注意機器人蔘數上要設置期貨合約代碼,並且配置的交易所對象需要是期貨交易所。amount
,交易數量。
運行測試
使用wexApp
模擬盤測試。
END
完整策略地址:https://www.fmz.com/strategy/221850
方案中的access_key
,secret_key
僅僅爲識別,對於使用http並無安全性。該方案僅僅作爲思路、拋磚引玉,實際應用應當增加安全方面的考慮,使用https
通信。
更新
-
由於
HTTPServer
本身有些坑,考慮使用ThreadingHTTPServer
代替。
參考:https://docs.python.org/3.7/library/http.server.html
需要Python3.7版本。 -
增加了GET請求測試
可以使用瀏覽器,地址欄輸入請求鏈接。http://xxx.xx.xx.xx/data?access_key=123&secret_key=123&type=buy&amount=1
測試:
-
增加了商品期貨連接狀態的判斷
HTTPServer
問題的資料:
https://www.zybuluo.com/JunQiu/note/1350528