TradingViewWebHook直连策略

Author: 小小梦, Date: 2020-08-03 09:58:19
Tags:

相关文章:https://www.fmz.com/bbs-topic/5969

由于HTTPServer本身有些坑,考虑使用ThreadingHTTPServer代替。 参考:https://docs.python.org/3.7/library/http.server.html 需要Python3.7版本。

HTTPServer问题的资料: https://www.zybuluo.com/JunQiu/note/1350528


'''
请求格式: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 re
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)
            
            # 测试POST请求Body信息            
            data = self.rfile.read(200)   # 指定了读取长度
            Log("data:", data)            # 打印POST请求的数据,可以根据请求中的数据具体再让机器人执行对应的操作
            
            # 校验
            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 "未设置期货合约"
                                
                q = None
                if exchange.GetName() == "Futures_CTP" and UseMarketOrderForCTP == False:
                    q = ext.NewTaskQueue()
                
                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")
                    if not q:
                        exchange.Buy(-1, float(dictParam["amount"]))
                    else :
                        q.pushTask(exchange, ContractType, "buy", float(dictParam["amount"]), lambda task, ret: Log(task["desc"], ret, "#FF0000"))
                    Log("持仓:", exchange.GetPosition())
                elif not isSpot and dictParam["type"] == "short":
                    exchange.SetDirection("sell")
                    if not q:
                        exchange.Sell(-1, float(dictParam["amount"]))
                    else :
                        q.pushTask(exchange, ContractType, "sell", float(dictParam["amount"]), lambda task, ret: Log(task["desc"], ret, "#FF0000"))
                    Log("持仓:", exchange.GetPosition())
                elif not isSpot and dictParam["type"] == "cover_long":
                    exchange.SetDirection("closebuy")
                    if not q:
                        exchange.Sell(-1, float(dictParam["amount"]))
                    else :
                        q.pushTask(exchange, ContractType, "closebuy", float(dictParam["amount"]), lambda task, ret: Log(task["desc"], ret, "#FF0000"))
                    Log("持仓:", exchange.GetPosition())
                elif not isSpot and dictParam["type"] == "cover_short":
                    exchange.SetDirection("closesell")
                    if not q:
                        exchange.Buy(-1, float(dictParam["amount"]))
                    else :
                        q.pushTask(exchange, ContractType, "closesell", float(dictParam["amount"]), lambda task, ret: Log(task["desc"], ret, "#FF0000"))
                    Log("持仓:", exchange.GetPosition())
                
                if q is not None:
                    while q.size() > 0:
                        q.poll()
                        Sleep(500)
            
            # 处理body数据
            if isDealBodyMsg:
                if exchange.GetName().find("Futures") != -1:
                    Log("data:", data.decode('utf-8'))  # 测试
                    if re.search(r'buy', data.decode('utf-8')):
                        Log("触发buy")
                        exchange.SetContractType(ct)
                        exchange.SetDirection("buy")
                        exchange.Buy(-1, amount)
                    elif re.search(r'sell', data.decode('utf-8')):
                        Log("触发sell")
                        exchange.SetContractType(ct)
                        exchange.SetDirection("sell")
                        exchange.Sell(-1, amount)
            
            # 写入数据应答
            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")    
    if exchange.GetName().find("Futures") != -1:
        exchange.SetContractType(ContractType)
    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)

More

eth8888 /upload/asset/2457669d9c32568732cb7.jpg 开启实盘提示这个错误,是哪里错了

eth8888 /upload/asset/2457669d9c32568732cb7.jpg 开启实盘提示这个错误,是哪里错了

华山论剑 老师:可以加个微信吗?

华山论剑 2021/11/21 11:53:33 CMD 199866 buy=0.1,托管者接到了这个信息,而机器人里没任何动作

superon 看了一晚上还是没看懂,能不能代写一下 聯繫一下V:maybeyeah

刘哲1 能不能写一个完整的tv信号下单的例子,怎么拿到body里面的信息。看的人云里雾里的

DietQuant 老师,怎么更改才可以单实盘增加双币种

梦想身价八位数 大神,能出一个OKv5模拟盘的出来吗?小白一个,不懂怎么弄,实盘的话又不敢

ssxxxd 老师请问个问题 3.7版本是 部署托管者的版本吗?怎么更新他呢 我试了好多次都提示 2021-08-11 11:08:55 错误 Traceback (most recent call last): File "<string>", line 999, in __init_ctx__ File "<string>", line 4, in <module> ImportError: cannot import name 'ThreadingHTTPServer' 2021-08-11 11:08:55 信息 商品期货交易类库加载成功 2021-08-11 11:08:55 信息 您使用的托管者 python编译环境的python版本是 3.5.

qq3390214355 看了一晚上还是没看懂,能不能代写一下,怎么联系呢

陈先森 老师您好,TV上直接报警交易方向的策略webhook地址怎么写?谢谢告知

lanbn 好的,谢谢老师,我测试一下!!!

lanbn 老师,您好,能不能把合约的一些代码写的详细一点,编程小白真的是无从下手,谢谢了!!

小小梦 FMZ API文档最后有OKEX切换模拟盘的函数。

wbe3-小薯条🍟 接收TV信号的策略,怎么切换模拟盘?老是提示我,环境不符

小小梦 报错是因为python没有相关的模块ThreadingHTTPServer

key986 这个问题你解决没有啊?

eth8888 搞清楚了

小小梦 不推荐这样创建服务监听TV的请求了,用FMZ的扩展API方式吧,文库里有文章。

小小梦 这个策略是以商品期货举例的,如果要跑数字货币的需要设置合约代码。改动一下策略。

小小梦 这个策略例子是直连的,就是策略机器人建立起了一个服务,用来监听来自TV的信号请求。 ``` # 测试POST请求Body信息 data = self.rfile.read(200) # 指定了读取长度 Log("data:", data) # 打印POST请求的数据,可以根据请求中的数据具体再让机器人执行对应的操作 ``` 代码里已经写了注释了,这里就是处理TV发来的请求的body信息。麻烦您看下代码。

小小梦 按照自己的需求修改策略。

小小梦 在FMZ上配置 OKEX 模拟盘的API KEY, 然后在代码中加上一句```exchange.IO("simulate", true)```切换就行了。

小小梦 不明白,估计是用的时候哪里搞错了,检查下。

陈先森 谢谢,如果我的webhook地址写的交易方向是买入,但tv策略报警的提示是卖出怎么办?(策略只提示买入卖出)

小小梦 https://www.fmz.com/bbs-topic/5969 文章和策略里有例子。

小小梦 https://www.fmz.com/api#exchange.setcontracttype... 函数描述中有,可以看下。

PY008 合约代码是什么?

小小梦 不客气。

小小梦 如果是做某个交易所的合约,把TV上的webhook地址写成: 做多一张合约: ``` http://x.x.x.x:xxxx/data?access_key=xxx&secret_key=yyy&type=long&amount=1 ``` 平多一张合约: ``` http://x.x.x.x:xxxx/data?access_key=xxx&secret_key=yyy&type=cover_long&amount=1 ``` 记得策略参数上,设置合约代码。