期限套利策略,要能够稳定获得各币种期货和现货的报价,计算各币种的基差数据,然后当基差突破阈值时触发交易。以下代码可以得到稳定报价,计算基差数据,然后当突破阈值时收到提示邮件(还没写好交易模块)。

这里记录一下,开发过程遇到的主要问题,以及如何解决的,如果不感兴趣,可以跳过,直接看代码。

问题一:websocket报价数据不更新

简单的ws.run_forever,通常在运行两三天后,会出现报价卡在某个时点,不能更新的情况。例如,现货报价停留在2021年12月25日11:00。

解决方案:用while true + try except语句,一旦websock链接有问题,就发送邮件通知(不知道为啥,一直没有收到报错邮件,发送邮件的代码可能有问题),回收内存,再重新链接。

    def s_start(self):while True:try:s_ws=WebSocketApp(url='wss://stream.binance.com:9443/ws',on_open=self._s_on_open,on_message=self._s_on_message,on_error=self._s_on_error,on_close=self._s_on_close)s_ws.run_forever() except Exception as e:content="%s the spot webscoket is broken,check if it restart"%eself._email(content)gc.collect()   

问题二:启动阶段报价数据为空

因为涉及到多币种,刚刚建立链接的时候,报价数据获取有先后,有可能btc数据有了,但是bnb数据要到10秒甚至20秒后才能收到。这样程序会因报错而中断。

解决方案:定义好报错的类型,用@retry装饰器,保证程序在遇到特定类型报错的时候,能够持续运行下去。

    def retry_if_index_error(exception):return isinstance(exception,IndexError)@retry(retry_on_exception=retry_if_index_error)def get_basis(self):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Dec  5 20:15:41 2021
It seems to work really good, the price and basis data is correct after running 13 days.
2021/12/13 16:30 begin
@author: yszhu
"""from websocket import WebSocketApp
import json,threading
import pysnooper
import time
import smtplib
from email.mime.text import MIMEText
from retrying import retry
import logging
import gcclass basis_dif(object):"""create variable save dilivery contract price,spot price and basis difference"""def __init__(self,contract_date=220325):#delivery contract priceself.d_eth_price=Noneself.d_eth_time=Noneself.d_btc_price=Noneself.d_btc_time=Noneself.d_bnb_price=Noneself.d_bnb_price=None#spot priceself.eth_price=Noneself.eth_time=Noneself.btc_price=Noneself.btc_time=Noneself.bnb_price=Noneself.bnb_time=None#delivery and spot basis differenceself.btc_basis_dif=Noneself.eth_basis_dif=Noneself.bnb_basis_dif=Noneself.contract_date=contract_dateself.basis_dif_threshold=0.035#emailself._mail_host="smtp.qq.com"self._mail_user="315960451"self._mail_pwd="brvjltflaofrbhcb"self._sender="youradress@qq.com"self._receivers="youradress@qq.com"# I use self._break_threshold to avoid sending email repeatedly.# when self._break_threshold = True ,it means the basis diffrence# now is greater than the threshold,so if the diffence becomes smaller# than the threshold, this is the first time of break during one operation period.# So ,I will receive the email ,and then operate my account.self._break_threshold = True#websocket for delivery contrat price def _d_on_open(self,d_ws):data={"method":"SUBSCRIBE","params":["btcusd_%s@aggTrade"%self.contract_date,"ethusd_%s@aggTrade"%self.contract_date,"bnbusd_%s@aggTrade"%self.contract_date],"id": 1}                        d_ws.send(json.dumps(data))def _d_on_message(self,d_ws,d_msg):d_msg=json.loads(d_msg)if 's' in d_msg and d_msg['s']=="BTCUSD_%s"%self.contract_date:self.d_btc_price=float(d_msg['p'])self.d_btc_time=d_msg['T']self.d_btc_time=int(self.d_btc_time/1000)self.d_btc_time=time.localtime(self.d_btc_time)self.d_btc_time=time.strftime("%Y-%m-%d %H:%M:%S",self.d_btc_time)if 's' in d_msg and d_msg['s']=="ETHUSD_%s"%self.contract_date:self.d_eth_price=float(d_msg['p'])self.d_eth_time=d_msg['T']self.d_eth_time=int(self.d_eth_time/1000)self.d_eth_time=time.localtime(self.d_eth_time)self.d_eth_time=time.strftime("%Y-%m-%d %H:%M:%S",self.d_eth_time)if 's' in d_msg and d_msg['s']=="BNBUSD_%s"%self.contract_date:self.d_bnb_price=float(d_msg['p'])self.d_bnb_time=d_msg['T']self.d_bnb_time=int(self.d_bnb_time/1000)self.d_bnb_time=time.localtime(self.d_bnb_time)self.d_bnb_time=time.strftime("%Y-%m-%d %H:%M:%S",self.d_bnb_time)def _d_on_close(self,d_ws):print("##connection closed##")def _d_on_error(self,d_ws,error):print(f"on error:{error}")def d_start(self):while True:try:d_ws=WebSocketApp(url='wss://dstream.binance.com/ws',on_open=self._d_on_open,on_message=self._d_on_message,on_error=self._d_on_error,on_close=self._d_on_close)d_ws.run_forever()except Exception as e:content="%s the future webscoket is broken,check if it restart"%eself._email(content)gc.collect()#websocket for spot price def _s_on_open(self,s_ws):data={"method": "SUBSCRIBE","params": ["btcusdt@aggTrade","ethusdt@aggTrade","bnbusdt@aggTrade"],"id": 2}               s_ws.send(json.dumps(data))def _s_on_message(self,s_ws,s_msg):s_msg=json.loads(s_msg)if 's' in s_msg and s_msg['s']=="BTCUSDT":self.btc_price=float(s_msg['p'])self.btc_time=s_msg['T']self.btc_time=int(self.btc_time/1000)self.btc_time=time.localtime(self.btc_time)self.btc_time=time.strftime("%Y-%m-%d %H:%M:%S",self.btc_time)if 's' in s_msg and s_msg['s']=="ETHUSDT":self.eth_price=float(s_msg['p'])self.eth_time=s_msg['T']self.eth_time=int(self.eth_time/1000)self.eth_time=time.localtime(self.eth_time)self.eth_time=time.strftime("%Y-%m-%d %H:%M:%S",self.eth_time)if 's' in s_msg and s_msg['s']=="BNBUSDT":self.bnb_price=float(s_msg['p'])self.bnb_time=s_msg['T']self.bnb_time=int(self.bnb_time/1000)self.bnb_time=time.localtime(self.bnb_time)self.bnb_time=time.strftime("%Y-%m-%d %H:%M:%S",self.bnb_time)def _s_on_close(self,s_ws):print("##connection closed##")def _s_on_error(self,s_ws,error):print(f"on error:{error}")def s_start(self):while True:try:s_ws=WebSocketApp(url='wss://stream.binance.com:9443/ws',on_open=self._s_on_open,on_message=self._s_on_message,on_error=self._s_on_error,on_close=self._s_on_close)s_ws.run_forever() except Exception as e:content="%s the spot webscoket is broken,check if it restart"%eself._email(content)gc.collect()   #because there are 7 kind of coin with spot and future price , so at#the begining , there maybe no data for self.bnb_price for the lack of liquidity,#In this case , python will raise IndexError#we need trying when TypeError is raised. def retry_if_index_error(exception):return isinstance(exception,IndexError)@retry(retry_on_exception=retry_if_index_error)def get_basis(self):while True:self.btc_basis_dif = self.d_btc_price/self.btc_price-1self.eth_basis_dif = self.d_eth_price/self.eth_price-1self.bnb_basis_dif = self.d_bnb_price/self.bnb_price-1print("btc_basis_dif is %f" % self.btc_basis_dif)print("btc_d_price is %f %s"%(self.d_btc_price,self.d_btc_time))print("btc_s_price is %f %s"%(self.btc_price,self.btc_time))print("eth_basis_dif is %f"%self.eth_basis_dif)print("eth_d_price is %f %s"%(self.d_eth_price,self.d_eth_time))print("eth_s_price is %f %s"%(self.eth_price,self.eth_time))print("bnb_basis_dif is %f"%self.bnb_basis_dif)print("bnb_d_price is %f %s"%(self.d_bnb_price,self.d_bnb_time))print("bnb_s_price is %f %s"%(self.bnb_price,self.bnb_time))basis_dif_dict={"btc":[self.btc_basis_dif,self.btc_price,self.d_btc_price],"eth":[self.eth_basis_dif,self.eth_price,self.d_eth_price],"bnb":[self.bnb_basis_dif,self.bnb_price,self.d_bnb_price],}basis_dif_dict=sorted(basis_dif_dict.items(),key=lambda x:x[1],reverse=True)greatest_basis_dif=basis_dif_dict[0][1][0]        print("the greatest basis is %s %f,Spot pirice %f,future price %f"%(basis_dif_dict[0][0],greatest_basis_dif,basis_dif_dict[0][1][1],basis_dif_dict[0][1][2]))if greatest_basis_dif>self.basis_dif_threshold:if self._break_threshold == True:content="the greatest basis is %s %f,Spot pirice %f,future price %f"%(basis_dif_dict[0][0],greatest_basis_dif,basis_dif_dict[0][1][1],basis_dif_dict[0][1][2])self._email(content)self._break_threshold = Falseif greatest_basis_dif<self.basis_dif_threshold:self._break_threshold= Truedef _email(self,content):'''if the basis_dif reached the threshold, send an emailparam:content: which coin's bais_dif has reach the threshold at what price and when'''message=MIMEText(content,'plain',"utf-8")message['Subject']="from new greatest basis dif:basis difference reached the threshold"message['From']=self._sendermessage['to']=self._receivers[0]smtpObj=smtplib.SMTP()smtpObj.connect(self._mail_host,25)smtpObj.login(self._mail_user,self._mail_pwd)smtpObj.sendmail(self._sender,self._receivers,message.as_string())smtpObj.quit()if __name__=="__main__":test=basis_dif()# because I want to recieve spot and contract price at the same time, so I create two threads t1=threading.Thread(target=test.d_start)t2=threading.Thread(target=test.s_start)t1.start()t2.start()test.get_basis()

binance 币本位交割合约期限套利交易(三)--获取基差数据相关推荐

  1. 【币圈小试牛刀】期现套利(上)——期限套利原理

    大家好!我是币圈玖哥,匆匆忙忙进场,匆匆忙忙进厂-提醒本文不构成任何投资建议,只是作为学习分享,本期给大家带来的策略是:期限套利,套取永续合约的资金费率,由于风险偏低,适合新手使用! 文章目录 1.期 ...

  2. 如何规避期货套利交易的陷阱

    我们都知道在套利交易中,就风险来说,相比单边交易风险要小得多:但是,尽管如此也不能放松对套利交易风险的控制,如果操作不当,套利交易也会造成滚雪球效应,损失也会一步一步扩大.那么如何规避套利交易的一些陷 ...

  3. 什么是套利?什么是套利交易

    什么是套利?套利是什么意思? 套利(Interest Arbitrage)   套利概述 在一般情况下,西方各个国家的利息率的高低是不相同的,有的国家利息率较高,有的国家利息率较低.利息率高低是国际资 ...

  4. 做空不再瞻前顾后!CoinBene满币USDT永续合约实盘上线(1)

    CoinBene满币 USDT永续合约体验争霸赛吸引了众多合约玩家参与其中,共计27位用户赢得2340USDT现金大奖.颁奖完成后,CoinBene满币正式上线USDT永续合约实盘交易,USDT永续合 ...

  5. 交割合约(期货合约)是什么?

    交割合约又称期货合约,是指在未来特定时间(交割日)以预定价格买卖标的资产的协定,是一种金融衍生品.与永续合约不同,交割合约会到期,有确定的到期日/交割日.当交割合约到期时,无论标的资产的实际价格如何, ...

  6. 开仓风险计算器.xlsx(可计算:名义价值、最大资金亏损、开仓所需保证金、开仓资金杠杆、最小逐仓保证金、U本位需开张数、币本位需开张数)

    这个excel版的开仓风险计算器我一年前就写好了,一直在用,后面还迭代了些新功能,如今的计算应该能满足绝大部分普通交易者的需求了. 不废话,上图: ↓ 点击卡片下载计算器 ↓ 开仓风险计算器.xlsx ...

  7. 股指期货的理论价格与期限套利

    股指期货的定价利用的是无风险套利原理,也就是说股指期货的价格应当消除无风险套利的机会,否则就会有人进行套利.对于一般的投资者来说,只要了解股指期货价格与现货指数.无风险利率.红利率.到期前时间长短有关 ...

  8. 如何运用债市杠杆套利交易博取收益

    如何运用债市杠杆套利交易博取收益 套利交易策略 在目前我国的固定收益市场中,合理运用套利交易策略可以获得超额收益,主要包括以下套利交易策略. 1)息差交易策略:指通过不断正回购融资并买入债券的策略,只 ...

  9. 大所交割合约到期情况观察

    ok交割合约到期时间 本季度:20210924(9月最后一个周五) 但策略运行到9月20日12点左右就停止了 9月22日重新运行后,out文件时间刷新,但内容无法刷新 发现是私钥没上传 上传后,重新运 ...

最新文章

  1. matlab解决多旅游商问题,多旅行商问题的matlab程序
  2. nginx 只写了listen80 没有 listen443 用https访问
  3. 本科 8年经验,20k的Offer,接还是不接?
  4. java实用教程——组件及事件处理——对话框(消息对话框,输入对话框,确认对话框)
  5. c语言中字符数字加'0',C语言中的NULL与转义字符'\0'以及数值0的关系
  6. mysql保留字-关键字表
  7. 关于RTB实时竞价的基本原理
  8. 50个经典jquery实例_【电气知识】从原理图到程序的4个经典实例详解
  9. 用maven按环境打包SpringBoot的不同配置文件
  10. VS编译错误:error C2143: 语法错误 : 缺少“;”(在“类型”的前面)
  11. iOS POST 上传图片
  12. 按头安利 好看又实用的布纹 布料贴图素材看这里
  13. 【Matlab绘图进阶第2弹】Matlab绘制论文柱状图
  14. 前端性能优化(三)——浏览器九大缓存方法
  15. 当img没有图片时候,显示默认图片代码
  16. 国产免费虚拟化OVM与 OpenStack对比
  17. 使用 VS 打开 VC++6.0 创建的 MFC 项目
  18. Ctone T01双卡双待Android 2.2的3.5英寸电容式多点触摸的GSM智能手机带GPS无线上网
  19. Android开源项目分类
  20. 磨金石教育||商业插画的发展现状如何?学习插画可以月入过万吗?

热门文章

  1. 离散数学---期末复习知识点
  2. echarts使主标题和副标题在同一行显示
  3. SPI _FLASH芯片W25Q16配置FATFS
  4. 一款修改字体(简繁转换)
  5. pycharm如何显示工具栏
  6. 服务器临时文件无法删掉,“internet临时文件”始终删不掉如何解决?临时文件无法删除的清理方法...
  7. TRIZ创新方法——剪裁
  8. 欧洲杯案例(数据过滤和排序)
  9. 《精彩人生的一分钟小习惯》读后感
  10. 详细答案2013百度校园招聘笔试题