Ctp接口 Tick数据转换成3秒钟,5秒钟,15秒钟,1分钟,3分钟,5分钟,n分钟周期的K线数据
图片为5秒钟 合成效果
完整源码
"""
关注公众号: Ctp接口量化
"""
import thostmduserapi as mdapi
from datetime import datetime
import time
import os, os.path
import random
import json
import threading
class MdSpi(mdapi.CThostFtdcMdSpi):
def __init__(self,setting,BaseGateway):
mdapi.CThostFtdcMdSpi.__init__(self)
# super().__init__()
self.userid = setting["userid"]
self.password = setting["password"]
self.brokerid = setting["brokerid"]
self.td_address = setting["td_address"]
self.md_address = setting["md_address"]
self.appid = setting["appid"]
self.auth_code = setting["auth_code"]
self.product_info = setting["product_info"]
self.threading = threading
self.reqid = 0
self.Gateway = BaseGateway
self.nest = {
}
self.api = self.create()
self.connect()
def create(self):
mdpath = os.getcwd() + '/' + self.userid + '/md/' #LOGS_DIR +"md"
if not os.path.exists(mdpath):
os.makedirs(mdpath)
return mdapi.CThostFtdcMdApi_CreateFtdcMdApi(mdpath)
def Bar(self, tick, granularity = 30):
instrument_id = tick.InstrumentID
action_day = tick.ActionDay
update_time = tick.UpdateTime.replace(':', '')
last_price = tick.LastPrice
volume = tick.Volume
if update_time.find('.') != -1:
dt = datetime.strptime(' '.join([action_day, update_time]), "%Y%m%d %H%M%S.%f")
timestamp = time.mktime(dt.timetuple()) + (dt.microsecond / 1e6)
else:
timestamp = int(time.mktime(time.strptime(' '.join([action_day, update_time]), "%Y%m%d %H%M%S")))
date_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp))
remainder = timestamp % granularity
if instrument_id not in self.nest:
self.nest[instrument_id] = {
'Date': date_time,
'Open': last_price,
'High': last_price,
'Low': last_price,
'Close': last_price,
'Volume': volume,
'last_time': timestamp,
}
else:
if remainder == 0 or (timestamp - self.nest[instrument_id]['last_time'])>= granularity:
self.nest[instrument_id]['Volume'] = volume - self.nest[instrument_id]['Volume']
self.nest[instrument_id]['Date'] = date_time
print(instrument_id,self.nest[instrument_id])
# self.Gateway.on_bar(tick,self.nest[instrument_id])
del self.nest[instrument_id]
else:
self.nest[instrument_id]['Date'] = date_time
self.nest[instrument_id]['Close'] = last_price
if last_price > self.nest[instrument_id]['High']:
self.nest[instrument_id]['High'] = last_price
elif last_price < self.nest[instrument_id]['Low']:
self.nest[instrument_id]['Low'] = last_price
def OnFrontConnected(self) -> "void":
print ("行情初始化")
self.login()
def login(self):
req = mdapi.CThostFtdcReqUserLoginField()
req.BrokerID = self.brokerid # 经纪公司代码
req.UserID = self.userid # 投资者代码
req.Password = self.password # 投资者代码
req.UserProductInfo = self.product_info
self.reqid += 1
self.api.ReqUserLogin(req,self.reqid)
def OnRspUserLogin(self, pRspUserLogin: 'CThostFtdcRspUserLoginField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool'):
print (f"OnRspUserLogin, SessionID={pRspUserLogin.SessionID},ErrorID={pRspInfo.ErrorID},ErrorMsg={pRspInfo.ErrorMsg}")
self.api.SubscribeMarketData([id.encode('utf-8') for id in self.Gateway.symbol_lsit],len(self.Gateway.symbol_lsit))
def OnRtnDepthMarketData(self, pDepthMarketData: 'CThostFtdcDepthMarketDataField') -> "void":
# self.threading.Thread(target=self.RenkoBar, args=(pDepthMarketData,self.Gateway.tick_time)).start()
# self.RenkoBar(pDepthMarketData,self.Gateway.tick_time)
# self.threading.Thread(target=self.Bar, args=(pDepthMarketData,self.Gateway.BarType)).start()
self.Bar(pDepthMarketData,self.Gateway.BarType)
self.Gateway.on_tick(pDepthMarketData)
def OnRspSubMarketData(self, pSpecificInstrument: 'CThostFtdcSpecificInstrumentField', pRspInfo: 'CThostFtdcRspInfoField', nRequestID: 'int', bIsLast: 'bool'):
print ("订阅 合约")
print ("InstrumentID=",pSpecificInstrument.InstrumentID)
# print ("ErrorID=",pRspInfo.ErrorID)
# print ("ErrorMsg=",pRspInfo.ErrorMsg)
def connect(self):
self.api.RegisterFront(self.md_address)
self.api.RegisterSpi(self)
self.api.Init()
self.api.Join()
def __del__(self):
self.api.RegisterSpi(None)
self.api.Release()
def SubMarketData(self, symbol):
Req = self.api.SubscribeMarketData([id.encode('utf-8') for id in symbol],len(symbol))
return Req
class BarType():
"""时间类型:秒,分,时,日,周,月,年"""
"""3秒"""
Time3 = 3
'''5秒'''
Time5 = 5
'''15秒'''
Time15 = 15
'''30秒'''
Time30 = 30
'''1分钟'''
Min = 60
'''3分钟'''
Min3 = 180
'''5分钟'''
Min5 = 300
'''15分钟'''
Min15 = 900
'''30分钟'''
Min30 = 1800
'''60分钟'''
Min60 = 3600
def __int__(self):
"""return int value"""
return self.value
class Strategy():
def __init__(self):
super().__init__()
self.symbol_lsit = ["ni2103","rb2105","ag2102","IF2103","IC2103","i2109","jm2109"] #订阅合约
self.BarType = BarType.Time5 #订阅K线周期 秒级 BarType.Time3 Time5 Time15 Time30 分钟级 BarType.Min、 Min3 、 Min5 、 Min15 、 Min30 、 Min60
def on_tick(self, tick=None):
print(tick.InstrumentID,tick.LastPrice)
def on_bar(self, tick=None, Bar=None):
symbol = tick.InstrumentID #合约代码
Bid = tick.BidPrice1 #买价
Ask = tick.AskPrice1 #卖价
LastPrice = tick.LastPrice #最新价
print(Bar) #合约
if __name__ == '__main__':
# Config 配置模板
# Config = {'brokerid':'9999', 'userid':'123456', 'password':'******', 'appid':'simnow_client_test', 'auth_code':'0000000000000000', 'product_info':'python dll', 'td_address':'tcp://180.168.146.187:10130', 'md_address':'tcp://180.168.146.187:10131'}
Config = {
'brokerid':'9999', 'userid':'123456', 'password':'******', 'appid':'simnow_client_test', 'auth_code':'0000000000000000', 'product_info':'python dll', 'td_address':'tcp://180.168.146.187:10101', 'md_address':'tcp://180.168.146.187:10111'}
t = MdSpi(Config,Strategy())