精华内容
下载资源
问答
  • 2013~2015期货TICK数据85GB种子
  • 原生的backtrader并不支持tick数据的回测,论坛里面也有一些使用者讨论如何用backtrader回测tick数据,其实,最近也一直有在思考这个问题,这篇文章就分享下,如何做。在开始之前,先分析下,这么做的一些缺点。 ...

    原生的backtrader并不支持tick数据的回测,论坛里面也有一些使用者讨论如何用backtrader回测tick数据,其实,最近也一直有在思考这个问题,这篇文章就分享下,如何做。在开始之前,先分析下,这么做的一些缺点。

    高频回测的测不准原理

    对于中低频的趋势交易策略,如果交易量不是很大的话,单个交易策略对市场的影响微乎其微,可以只考虑市场什么情况,在这种情况下,考虑交易成本之后,回测有一定的可靠性。

    高频的交易,本身可能对这个市场就有很大的影响,自身的行为就可能导致市场行为发生改变,使用历史数据回测,即使不考虑交易成本,也很难得到准确的结果。听说,很多高频策略都是直接上模拟盘,小仓位测试,到实盘。高频策略主要是靠理论支撑的,主要是以速度制胜,回测可能没有那么重要。

    上面是一个没有做过高频策略的quant的一家之言,也可能不准确哈,仅供参考。

    用python去回测tick数据的不足

    backtrader是基于python的量化交易框架,python作为一门解释性语言,相对于C++等编译性语言,运行速度会慢上好多。而tick数据本身数据量就比较多,导致python写的量化框架,回测tick数据的时候,都需要耗时比较多。

    backtrader本身机制比较完善,里面的order等,自带了丰富的信息,会导致在运行的过程中,内存会不断增大,如果回测的tick数据比较多,几十个G的内存很有可能不够。

    总结一下,使用python本身速度比较慢,使用backtrader会额外消耗内存,导致,用backtrader回测大量的tick数据,是一个又慢又占内存的事,是一个事半功倍的努力。

    为什么还要用backtrader来回测tick数据

    • 不会c++等语言是一个限制

      如果是专门做高频的策略的话,建议就换个平台吧。不要用backtrader了,即使用backtrader,实盘的时候也得改平台。用python去做高频,如果你有一颗慈善的心,愿意捐钱的话,当我没说。

    • 没找到其他更好的python框架

      python语言很容易学,有很多基于python的量化框架。但是,到目前为止,还没有找到,或者没有注意到,有哪家是能够支持tick数据的回测的。

    • backtrader本身有很大的优势

      backtrader的优势,就不需要我一遍遍去强调了。

    如何用backtrader来回测期货的tick数据

    因为backtrader对数据提供了很好的扩展功能,对于高开低收成交量持仓量等之外的数据,可以很容易添加进来。具体的扩展数据的案例,可以参考本文。

    如果要改造tick数据,应该怎么做呢?

    1. 期货的tick数据,都包含哪些内容?

    这是我用一个软件采集的期货的tick数据,包含了下面的字段:

    localtime (本机写入TICK的时间),
    InstrumentID (合约名),
    TradingDay (交易日),
    ActionDay (业务日期),
    UpdateTime (时间),
    UpdateMillisec(时间毫秒),
    LastPrice (最新价),
    Volume(成交量) ,
    HighestPrice (最高价),
    LowestPrice(最低价) ,
    OpenPrice(开盘价) ,
    ClosePrice(收盘价),
    AveragePrice(均价),
    AskPrice1(申卖价一),
    AskVolume1(申卖量一),
    BidPrice1(申买价一),
    BidVolume1(申买量一),
    UpperLimitPrice(涨停板价)
    LowerLimitPrice(跌停板价)
    OpenInterest(持仓量),
    Turnover(成交金额),
    PreClosePrice (昨收盘),
    PreOpenInterest (昨持仓),
    PreSettlementPrice (上次结算价),

    2. backtrader在回测的时候需要传入的数据

    backtrader传入数据的时候,一般都是需要使用到open\high\low\close这四个价格,为了符合回测的逻辑,让最新价等于open\high\low\close,并且可以额外添加几个列,比如AskVolume1(卖量一),BidVolume1(买量一)。

    这样做有一个缺陷:使用限价单的时候,其实并不能知道能不能成交。比如价格6元的买订单,最新价在5.9元的时候,是会成交的,但是并不能知道最新价在6.00的时候会不会成交。这是一个缺陷。

    如果想要避免这个,就需要开发逐tick回测的模式。

    目前这个只是基于bar进行的改造,是对现实的一个逼近。理论上是存在更好的回测方法的。

    处理原始数据,生成backtrader需要的数据
    import pandas as pd
    import numpy as np
    data = pd.read_csv("c:/result/rb2105.csv")
    data['datetime']=pd.to_datetime([str(x)+" "+str(y)+"."+str(z) for x,y,z in zip(data['ActionDay'], data["UpdateTime"],data['UpdateMillisec'])])
    data['open'] = data['LastPrice']
    data['close'] = data['LastPrice']
    data['high'] = data['LastPrice']
    data['low'] = data['LastPrice']
    data['volume'] = data['Volume']
    data= data[['datetime','open','high','low','close','volume','AskPrice1','AskVolume1','BidPrice1','BidVolume1']]
    data.to_csv("rb2105.csv",index=False)
    
    3. 使用backtrader回测期货tick数据的一个小案例

    注:这个策略是toy strategy,仅仅是为了测试tick数据随手编写的,大家可以根据自己的需要,改进相关的策略逻辑。

    import backtrader as bt
    from backtrader import num2date
    import datetime
    # 在交易信息之外,额外增加了PE、PB指标,做涉及到基本面信息的策略使用
    class GenericTickCSV(bt.feeds.GenericCSVData):
    
        # 增加两个line,每个line的名称,就是csv文件中,额外增加的列的名称
        lines = ('AskPrice1','AskVolume1','BidPrice1','BidVolume1',)
    
        # 具体每个新增加的变量index是多少,要根据自己的csv文件去决定,从0开始数
        params = (('AskPrice1',6),('AskVolume1',7),('BidPrice1',8),('BidVolume1',9))
        
    # 我们使用的时候,直接用我们新的类读取数据就可以了。
    class TestTickStrategy(bt.Strategy):
       
        params = (('window',200),)
    
        def log(self, txt, dt=None):
            ''' Logging function fot this strategy'''
            dt = dt or num2date(self.datas[0].datetime[0])
            print('{}, {}'.format(dt.isoformat(), txt))
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.bar_num=0
            # 持仓状态
            self.marketposition = 0
           
        def prenext(self):
            
            pass 
            
        def next(self):
            # 假设有100万资金,每次成份股调整,每个股票使用1万元
            self.bar_num+=1
            # 获取并打印当前的数据
            data = self.datas[0]
            now_datetime = num2date(data.datetime[0])
            now_open = data.open[0]
            now_high = data.high[0]
            now_low = data.low[0]
            now_close = data.close[0]
            # 卖一价、量
            now_ask_volume = data.AskVolume1[0]
            now_ask_price = data.AskPrice1[0]
            # 买一价、量
            now_bid_price = data.BidPrice1[0]
            now_bid_volume = data.BidVolume1[0]
            # 输出信息
            self.log(f"now_open\high\low\close\lastprice:{now_open},\
                    now_ask_volume:{now_ask_volume},\
                    now_ask_volume:{now_ask_volume},\
                    now_bid_price:{now_bid_price},\
                   now_bid_volume:{now_bid_volume}")
            hold_size = self.getposition(data).size
            # 平仓
            if  self.bar_num%120 == 0:
                
                # 限价买单没成交
                if self.buy_order is not None and self.marketposition == 1:
                    self.cancel(self.buy_order)
                    self.buy_order = None
                # 限价卖单没成交
                if self.sell_order is not None and hold_size>0:
                    self.cancel(self.sell_order)
                    self.sell_order = None
                    # 平仓
                    self.close()
                self.marketposition = 0 
            # 开仓
            if hold_size == 0 and self.marketposition==0 and self.bar_num%120==0:
                
                self.buy_order = self.buy(self.datas[0],size = 1,exectype=bt.Order.Limit,price = now_bid_price-1)
                self.marketposition = 1
            # 限价单平仓
            if self.marketposition == 1 and hold_size>0 and  self.bar_num%120!=0:
               
                self.sell_order = self.sell(self.datas[0],size = 1,exectype=bt.Order.Limit,price = now_ask_price+2)
                self.marketposition = 0
                
                
        def notify_order(self, order):
            
            if order.status in [order.Submitted, order.Accepted]:
                return
            
            if order.status == order.Rejected:
                self.log(f"Rejected : order_ref:{order.ref}  data_name:{order.p.data._name}")
                
            if order.status == order.Margin:
                self.log(f"Margin : order_ref:{order.ref}  data_name:{order.p.data._name}")
                
            if order.status == order.Cancelled:
                self.log(f"Concelled : order_ref:{order.ref}  data_name:{order.p.data._name}")
                
            if order.status == order.Partial:
                self.log(f"Partial : order_ref:{order.ref}  data_name:{order.p.data._name}")
             
            if order.status == order.Completed:
                if order.isbuy():
                    self.log(f" BUY : data_name:{order.p.data._name} price : {order.executed.price} , cost : {order.executed.value} , commission : {order.executed.comm}")
    
                else:  # Sell
                    self.log(f" SELL : data_name:{order.p.data._name} price : {order.executed.price} , cost : {order.executed.value} , commission : {order.executed.comm}")
        
        def notify_trade(self, trade):
            # 一个trade结束的时候输出信息
            if trade.isclosed:
                self.log('closed symbol is : {} , total_profit : {} , net_profit : {}' .format(
                                trade.getdataname(),trade.pnl, trade.pnlcomm))
                # self.trade_list.append([self.datas[0].datetime.date(0),trade.getdataname(),trade.pnl,trade.pnlcomm])
                
            if trade.isopen:
                self.log('open symbol is : {} , price : {} ' .format(
                                trade.getdataname(),trade.price))
        def stop(self):
            
            pass 
            
            
            
        
    params = dict(
                fromdate = datetime.datetime(2021,1,4), # 回测开始时间
                todate = datetime.datetime(2021,3,20),  # 回测结束时间
                timeframe = bt.TimeFrame.Ticks,
                compression = 1,
                dtformat=('%Y-%m-%d %H:%M:%S.%f'), # 日期和时间格式
                tmformat=('%H:%M:%S.%f'), # 时间格式
                datetime=0, # 下面几行是导入的数据,要和传入的数据列进行一一对应,以这个参数为准
                high=2,
                low=3,
                open=1,
                close=4,
                volume=5,
                openinterest=-1)
    
    
         
    # 初始化cerebro,获得一个实例
    cerebro = bt.Cerebro()
    # cerebro.broker = bt.brokers.BackBroker(shortcash=True)  # 0.5%
    # 读取数据
    feed = GenericTickCSV(dataname = "rb2105.csv",**params)
    # 添加数据到cerebro
    cerebro.adddata(feed, name = "rb2105")
    # 添加手续费,按照万分之五收取
    cerebro.broker.setcommission(commission=0.0005,stocklike=False)
    # 设置初始资金为100万
    cerebro.broker.setcash(1000000.0)
    # 添加策略
    cerebro.addstrategy(TestTickStrategy)
    # 运行回测
    cerebro.run()
    # 画图
    cerebro.plot()
    

    在这里插入图片描述

    使用数据

    链接: https://pan.baidu.com/s/12nB0yHMgo_AQ_pz9s0PfTQ 提取码: djzi 复制这段内容后打开百度网盘手机App,操作更方便哦

    展开全文
  • 股指期货tick

    2014-07-15 09:55:12
    股指期货tick数据收集器,可以搜集分笔tick数据
  • 金融tick成交数据,格式:时间/ 价格/ 现量/增仓,用于分析回测等,非常有价值,懂的人会懂
  • 2、在共享内存中存放当个交易日的tick数据,方便随时取用。 3、支持多行情源取数据。经过测试一个行情源峰值带宽要求为20M,所以使用时要配合带宽限制。 4、夜盘结束时输出一下tick数据,白盘结束时输出所有tick。...

    功能:

    1、开启之后,7*24自动运行。

    2、在共享内存中存放当个交易日的tick数据,方便随时取用。

    3、支持多行情源取数据。经过测试一个行情源峰值带宽要求为20M,所以使用时要配合带宽限制。

    4、夜盘结束时输出一下tick数据,白盘结束时输出所有tick。

    5、支持查询指令:

     

     

     运行时如下:

    贴上代码:

    // FutureDataReceive.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "ThostFtdcMdSpiImpl.hpp"
    #include "ThostFtdcTraderSpiImpl.hpp"
    #include "future_helper.h"
    #include "TinyConfig.h"
    #include "FileMap.h"
    #include <boost/lockfree/queue.hpp>
    #include <iostream>
    #include <conio.h>
    
    CFileMap g_fileMap;
    TinyConfig g_config;
    CThostFtdcTraderSpiImpl g_trade;
    vector<shared_ptr<CThostFtdcMdSpiImpl>> g_vecQuote;
    
    int g_nPreTradingDay;
    int g_nTradingDay;
    bool g_bThread = true;
    
    boost::lockfree::queue<CThostFtdcDepthMarketDataField> g_buffer(1000);
    shared_ptr<thread> g_thdDealData = nullptr;
    vector<CThostFtdcDepthMarketDataField> g_vecBuffer;
    
    void OnLog(const char* p)
    {
    	printf(p);
    	ofstream ofs_log("./log.data.receive.txt", ios_base::app);
    	ofs_log << future_helper::get_local_datetime().c_str() << " " << p;
    	ofs_log.close();
    }
    
    #pragma region trade module
    ///trade call back
    bool g_bTradeLoginIn = false;
    void OnTradeComplete()
    {
    	int nTradingDay = atoi(g_trade.GetTradingDay());
    	if (g_nTradingDay != 0 && g_nTradingDay != nTradingDay)
    		g_nPreTradingDay = g_nTradingDay;
    
    	g_nTradingDay = nTradingDay;
    	g_bTradeLoginIn = true;
    	printf("交易日:%d-%d\n", g_nPreTradingDay, g_nTradingDay);
    }
    
    void OnTradeRspMessage(const char* from, const char* msg, future_msg_type msg_type)
    {
    	OnLog(future_helper::format_string("%s%s:%s\n", msg_type == future_msg_type::CTP_SUCCESS ? "" : "*", from, msg).c_str());
    }
    
    void TradeLogin()
    {
    	int retry_time = 3;
    	while (1)
    	{
    		g_bTradeLoginIn = false;
    		g_trade.SetCallBackFunc(OnTradeComplete, nullptr, OnTradeRspMessage);
    		g_trade.SetAuthenticate(g_config.GetValue("Trade", "product").c_str(), g_config.GetValue("Trade", "id").c_str(), g_config.GetValue("Trade", "code").c_str());
    		g_trade.InitParams(g_config.GetValue("Trade", "ip").c_str(), g_config.GetValue("Trade", "broker").c_str(),
    			g_config.GetValue("Trade", "user").c_str(), g_config.GetValue("Trade", "password").c_str());
    
    		int tick = GetTickCount();
    		while (1)
    		{
    			if (g_bTradeLoginIn) break;
    			this_thread::sleep_for(chrono::milliseconds(100));
    			if (GetTickCount() - tick > 60 * 1000) break;
    		}
    
    		g_trade.Release();
    		g_fileMap.SetTradingDay(g_nPreTradingDay, g_nTradingDay);
    		if (g_bTradeLoginIn) break;
    		retry_time--;
    		OnLog("交易 登录超时[1分钟],重新登录\n");
    		if (retry_time == 0)
    		{
    			OnLog("交易 登录次数达到3次,不再尝试重新登录!\n");
    			break;
    		}
    	}
    }
    //
    #pragma endregion trade module
    
    ///market call back
    int g_nMarketLoginIn = 0;
    void OnMarketComplete()
    {
    	g_nMarketLoginIn++;
    }
    
    void OnMarketRspMessage(const char* from, const char* msg, future_msg_type msg_type)
    {
    	OnLog(future_helper::format_string("%s%s:%s\n", msg_type == future_msg_type::CTP_SUCCESS ? "" : "*", from, msg).c_str());
    }
    
    void OnDepthMarketData(CThostFtdcDepthMarketDataField* p)
    {
    	if (!p) return;
    	g_buffer.push(*p);
    }
    
    void MarketLogin()
    {
    	int retry_time = 3;
    	std::vector<CThostFtdcInstrumentField> vecTradingCode;
    	g_trade.GetTradingCode(vecTradingCode, THOST_FTDC_PC_Futures);
    	g_trade.GetTradingCode(vecTradingCode, THOST_FTDC_PC_Options);
    	printf("订阅合约:%d\n", vecTradingCode.size());
    	g_fileMap.SetTradingCode(vecTradingCode);
    	while (1)
    	{
    		g_nMarketLoginIn = 0;
    		for (int i = 1; i <= 3; i++)
    		{
    			string this_ip = g_config.GetValue("Market", future_helper::format_string("ip%d", i).c_str());
    			if (this_ip == "") break;
    			auto pMdSpi = make_shared<CThostFtdcMdSpiImpl>();
    			g_vecQuote.push_back(pMdSpi);
    			pMdSpi->SetTradingCode(vecTradingCode);
    			pMdSpi->SetCallBackFunc(OnDepthMarketData, OnMarketRspMessage, nullptr, OnMarketComplete);
    			pMdSpi->InitParams(this_ip.c_str(), "8888", "88888888", "88888888");
    		}
    
    		int tick = GetTickCount();
    		while (1)
    		{
    			if (g_nMarketLoginIn == g_vecQuote.size()) break;
    			this_thread::sleep_for(chrono::milliseconds(100));
    			if (GetTickCount() - tick > 60 * 1000) break;
    		}
    
    		if (g_nMarketLoginIn > 0 && g_nMarketLoginIn != g_vecQuote.size())
    		{
    			int nUnconnectIndex = 1;
    			OnLog("***********************\n");
    			OnLog("*有未能正常登录的行情账号:\n");
    			for (auto iter = g_vecQuote.begin(); iter != g_vecQuote.end(); iter++)
    			{
    				if (!(*iter)->IsConnected())
    				{
    					OnLog(future_helper::format_string("%d、%s\n", nUnconnectIndex, (*iter)->GetFrontIP()).c_str());
    					nUnconnectIndex++;
    				}
    			}
    			OnLog("***********************\n");
    			OnLog("已有行情连接成功,未连接的不尝试重连\n");
    		}
    
    		if (g_nMarketLoginIn > 0) break;
    		OnLog("行情 登录超时[1分钟],重新登录\n");
    		retry_time--;
    		if (retry_time == 0)
    		{
    			OnLog("行情 登录次数达到3次,不再尝试重新登录!\n");
    			break;
    		}
    	}
    }
    
    void ThreadConsumeTick()
    {
    	OnLog("处理线程已启动\n");
    	map<string, CThostFtdcDepthMarketDataField> m_mapShot;
    	while (g_bThread)
    	{
    		if (g_buffer.empty())
    		{
    			this_thread::sleep_for(chrono::milliseconds(5));
    			continue;
    		}
    
    		CThostFtdcDepthMarketDataField data;
    		g_buffer.pop(data);
    		if (data.UpdateTime[2] == ':') {
    			data.UpdateTime[2] = data.UpdateTime[3];
    			data.UpdateTime[3] = data.UpdateTime[4];
    			data.UpdateTime[4] = data.UpdateTime[6];
    			data.UpdateTime[5] = data.UpdateTime[7];
    			data.UpdateTime[6] = 0;
    		}
    		
    		if (atoi(data.UpdateTime) > 180000) {
    			_snprintf_s(data.TradingDay, 9, "%d", g_nPreTradingDay);
    		}
    		else {
    			_snprintf_s(data.TradingDay, 9, "%d", g_nTradingDay);
    		}
    
    		bool bNewTick = false;
    		auto find_shot = m_mapShot.find(data.InstrumentID);
    		if (find_shot == m_mapShot.end())
    		{
    			bNewTick = true;
    			m_mapShot[data.InstrumentID] = data;
    		}
    		else
    		{
    			long long llThis = future_helper::to_longlong(atoi(data.TradingDay), atoi(data.UpdateTime)) * 1000 + data.UpdateMillisec;
    			long long llLast = future_helper::to_longlong(atoi(find_shot->second.TradingDay), atoi(find_shot->second.UpdateTime)) * 1000 + find_shot->second.UpdateMillisec;
    			if (llThis > llLast || find_shot->second.Volume < data.Volume)
    			{//郑商所没有毫秒
    				bNewTick = true;
    				find_shot->second = data;
    			}
    		}
    
    		if (bNewTick && g_fileMap.IsOK()) {
    			g_fileMap.AddDepthData(&data);
    		}
    		else if (bNewTick) {
    			g_vecBuffer.push_back(data);
    		}
    	}
    	OnLog("处理线程已退出\n");
    }
    
    //bReset == true:清空共享内存中的tick数据
    void OutPutTickData(bool bReset)
    {
    	unsigned int* exist_size;
    	CThostFtdcDepthMarketDataField* p = g_fileMap.GetDepthData(&exist_size);
    	if (!p || *exist_size <= 0) {
    		OnLog("共享内存中无任何tick数据\n从内存中导出\n");
    
    		if (g_vecBuffer.size() == 0)
    		{
    			OnLog("内存中无任何tick数据\n");
    			return;
    		}
    
    		future_helper::safe_create_floder((g_config.GetValue("Path", "tick_normal") + "\\" + future_helper::to_string(g_nTradingDay / 10000)).c_str());
    		ofstream ofs_tick(g_config.GetValue("Path", "tick_normal") + "\\" + future_helper::to_string(g_nTradingDay / 10000) +
    			"\\data_" + future_helper::to_string(g_nTradingDay) + ".txt", ios_base::out);
    		for (auto& field : g_vecBuffer)
    		{
    			char szBuf[1024];
    			_snprintf_s(szBuf, 1024,
    				//交易日,最后修改时间,最后修改毫秒,合约代码,
    				//最新价,上次结算价,昨收盘,昨持仓量,
    				//今开盘,最高价,最低价,数量,成交金额,持仓量,
    				//涨停板价,跌停板价,
    				//申买价一,申买量一,申卖价一,申卖量一,
    				//当日均价
    				"%s,%s,%d,%s,%.4f,%.4f,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%.4f,%d,%.4f\n",
    				field.TradingDay, field.UpdateTime, field.UpdateMillisec, field.InstrumentID,
    				field.LastPrice, field.PreSettlementPrice, field.PreClosePrice, field.PreOpenInterest,
    				field.OpenPrice, field.HighestPrice, field.LowestPrice, field.Volume, field.Turnover, field.OpenInterest,
    				field.UpperLimitPrice, field.LowerLimitPrice,
    				field.BidPrice1, field.BidVolume1, field.AskPrice1, field.AskVolume1,
    				field.AveragePrice);
    			ofs_tick << szBuf;
    		}
    		return;
    	}
    
    	OnLog(future_helper::format_string("输出共享内存中的tick数据 %d 个\n", *exist_size).c_str());
    	future_helper::safe_create_floder((g_config.GetValue("Path", "tick_normal") + "\\" + future_helper::to_string(g_nTradingDay / 10000)).c_str());
    	ofstream ofs_tick(g_config.GetValue("Path", "tick_normal") + "\\" + future_helper::to_string(g_nTradingDay / 10000) +
    		"\\data_" + future_helper::to_string(g_nTradingDay) + ".txt", ios_base::out);
    	for (int i = 0; i < *exist_size; i++)
    	{
    		auto& field = *(CThostFtdcDepthMarketDataField*)(p + i);
    		char szBuf[1024];
    		_snprintf_s(szBuf, 1024,
    			//交易日,最后修改时间,最后修改毫秒,合约代码,
    			//最新价,上次结算价,昨收盘,昨持仓量,
    			//今开盘,最高价,最低价,数量,成交金额,持仓量,
    			//涨停板价,跌停板价,
    			//申买价一,申买量一,申卖价一,申卖量一,
    			//当日均价
    			"%s,%s,%d,%s,%.3f,%.4f,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%.4f,%d,%.4f",
    			field.TradingDay, field.UpdateTime, field.UpdateMillisec, field.InstrumentID,
    			future_helper::check_double(field.LastPrice), future_helper::check_double(field.PreSettlementPrice), future_helper::check_double(field.PreClosePrice), future_helper::check_double(field.PreOpenInterest),
    			future_helper::check_double(field.OpenPrice), future_helper::check_double(field.HighestPrice), future_helper::check_double(field.LowestPrice), field.Volume, future_helper::check_double(field.Turnover), future_helper::check_double(field.OpenInterest),
    			future_helper::check_double(field.UpperLimitPrice), future_helper::check_double(field.LowerLimitPrice),
    			future_helper::check_double(field.BidPrice1), field.BidVolume1, future_helper::check_double(field.AskPrice1), field.AskVolume1,
    			future_helper::check_double(field.AveragePrice));
    		ofs_tick << szBuf << endl;
    	}
    	ofs_tick.flush();
    	ofs_tick.close();
    
    	if (bReset)
    		*exist_size = 0;
    }
    
    void Open()
    {
    	printf("%s\n", future_helper::get_local_datetime().c_str());
    	g_nMarketLoginIn = 0;
    	OnLog("区间交易开始!\n");
    	if (!g_thdDealData) {
    		g_bThread = true;
    		g_thdDealData = make_shared<thread>(ThreadConsumeTick);
    	}
    
    	if (!g_fileMap.CreateFileMap(FILE_MAP_KEY))
    	{
    		OnLog("共享内存创建失败!直接存文件...\n");
    	}
    	else
    	{
    		g_fileMap.InitDefaultRange();
    	}
    
    	TradeLogin();
    	unsigned int* exist_count;
    	auto pTick = g_fileMap.GetDepthData(&exist_count);
    	int local_time = atoi(future_helper::get_local_time(false).c_str());
    	if ((!pTick || *exist_count == 0) && (local_time < 151500 || local_time > 180000))
    	{
    		ifstream ifs_tick(g_config.GetValue("Path", "tick_normal") + "\\" + future_helper::to_string(g_nTradingDay / 10000) +
    			"\\data_" + future_helper::to_string(g_nTradingDay) + ".txt", ios_base::in);
    		if (ifs_tick.is_open())
    		{
    			OnLog("本地加载tick到共享内存:");
    			int tick_count = 0;
    			CThostFtdcDepthMarketDataField data;
    			char szLine[1024];
    			while (ifs_tick.getline(szLine, 1024))
    			{
    				future_helper::LineToStruct(szLine, data);
    				g_fileMap.AddDepthData(&data);
    				tick_count++;
    			}
    			OnLog(future_helper::format_string("%d条\n", tick_count).c_str());
    		}
    	}
    	MarketLogin();
    }
    
    void Close()
    {
    	printf("%s\n", future_helper::get_local_datetime().c_str());
    	int close_count = 0;
    	for (auto& md : g_vecQuote)
    	{
    		if (md->IsConnected()) {
    			close_count++;
    			md->ReleaseAPI();
    		}
    	}
    	g_vecQuote.clear();
    	if (close_count > 0) {
    		OnLog(future_helper::format_string("区间交易结束!关闭行情接收:%d\n", close_count).c_str());
    		if (g_thdDealData && g_thdDealData->joinable()) {
    			g_bThread = false;
    			g_thdDealData->join();
    			g_thdDealData = nullptr;
    		}
    	}
    
    	g_nMarketLoginIn = 0;
    	OnLog(future_helper::format_string("共享内存使用%d/%d(mb)=%.2f%%%%\n",
    		g_fileMap.GetTotalUsedSpace() / 1024 / 1024, MAX_PAGE_SIZE / 1024 / 1024,
    		(double)g_fileMap.GetTotalUsedSpace() * 100 / MAX_PAGE_SIZE).c_str());
    }
    
    
    int main()
    {
    	if (!g_config.Open((future_helper::GetWorkingDir() + "\\system.ini").c_str()))
    	{
    		OnLog("system.ini打开失败\n");
    		system("pause");
    	}
    
    	OnLog("执行开启共享内存测试...");
    	if (!g_fileMap.CreateFileMap(FILE_MAP_KEY))
    	{
    		OnLog("失败!");
    		system("pause");
    	}
    	else
    	{
    		OnLog("成功!\n");
    		g_fileMap.Release();
    	}
    
    	OnLog("==========start==========\n");
    
    	printf("初次启动需要输入前交易日,用来更新夜盘的日期...");
    	scanf_s("%d", &g_nPreTradingDay);
    	int night_tick_count = -1;
    	int last_local_time = atoi(future_helper::get_local_time(false).c_str());
    
    	while (1)
    	{
    		if (_kbhit() != 0)
    		{
    			printf("**********不要长时间阻塞此处,这样将导致软件无法正常工作!***********\n");
    			printf("**********记得输入完之后按回车键哦!                      ***********\n");
    			string str;
    			std::getline(std::cin, str);
    			if (str == "quit")
    			{
    				Close();
    				break;
    			}
    			else if (str == "help")
    			{
    				printf("quit:退出\n");
    				printf("help:帮助\n");
    				printf("open:手动开启接收\n");
    				printf("close:手动关闭接收\n");
    				printf("tradingday:交易日\n");
    				printf("tradingcode:可交易合约\n");
    				printf("tickdata:输出接收到的tick数据\n");
    				printf("sharememory:共享内存使用率\n");
    			}
    			else if (str == "open")
    			{
    				Open();
    			}
    			else if (str == "close")
    			{
    				Close();
    			}
    			else if (str == "tradingday")
    			{
    				printf("交易日:%d-%d\n", g_nPreTradingDay, g_nTradingDay);
    			}
    			else if (str == "tradingcode")
    			{
    				printf("期货可交易合约:\n");
    				map<string, vector<CThostFtdcInstrumentField>> mapClasses;
    				vector<CThostFtdcInstrumentField> vec;
    				g_trade.GetTradingCode(vec, THOST_FTDC_PC_Futures);
    				for (auto& item : vec)
    				{
    					mapClasses[item.ProductID].push_back(item);
    				}
    
    				for (auto iter = mapClasses.begin(); iter != mapClasses.end(); iter++)
    				{
    					printf("%s:", iter->first.c_str());
    					for (auto& item : iter->second)
    					{
    						printf("%s ", item.InstrumentID);
    					}
    					printf("\n");
    				}
    			}
    			else if (str == "tickdata")
    			{
    				OutPutTickData(false);
    			}
    			else if (str == "sharememory")
    			{
    				unsigned int* exist_size;
    				CThostFtdcDepthMarketDataField* p = g_fileMap.GetDepthData(&exist_size);
    				OnLog(future_helper::format_string("tick数据个数:%d\n共享内存使用%d/%d(mb)=%.2f%%%%\n",
    					p ? *exist_size : 0,
    					g_fileMap.GetTotalUsedSpace() / 1024 / 1024, MAX_PAGE_SIZE / 1024 / 1024,
    					(double)g_fileMap.GetTotalUsedSpace() * 100 / MAX_PAGE_SIZE).c_str());
    			}
    		}
    
    		int local_time = atoi(future_helper::get_local_time(false).c_str());
    		if ((local_time >= 23500 && last_local_time < 23500) ||
    			(local_time >= 155000 && last_local_time < 155000))
    		{
    			unsigned int* exist_count;
    			auto pTick = g_fileMap.GetDepthData(&exist_count);
    			Close();
    			if ((local_time >= 155000 && last_local_time < 155000)){
    				OnLog("交易日结束了?...");
    				if (night_tick_count == -1 || *exist_count > night_tick_count) {
    					OnLog("是的!\n");
    					OutPutTickData(true);
    					if (night_tick_count != -1) {
    						OnLog("打开TickToKline.exe\n");
    						::ShellExecute(NULL, "open", (future_helper::GetWorkingDir() + "\\TickToKline.exe").c_str(), "1", NULL, SW_SHOW);
    					}
    					
    					night_tick_count = -1;
    				}
    				else
    				{
    					OnLog(future_helper::format_string("没有!(共享内存的数据没有比夜盘多%d-%d)!\n",
    						night_tick_count, *exist_count).c_str());
    				}
    			}
    			else
    			{
    				OnLog("夜盘结束了?...");
    				if (night_tick_count == -1 && *exist_count > 0) {
    					OnLog("是的!输出一次夜盘数据\n");
    					night_tick_count = *exist_count;
    					OutPutTickData(false);
    				}
    				else
    				{
    					OnLog("现在不是夜盘结束时间!(没有夜盘数据 或者 已经输出过一次夜盘数据了)\n");
    				}
    			}
    		}
    		if ((local_time >= 82000 && last_local_time < 82000) ||
    			(local_time >= 202000 && last_local_time < 202000))
    		{
    			Close();
    			Open();
    		}
    
    		last_local_time = local_time;
    		this_thread::sleep_for(chrono::seconds(1));
    	}
    
        return 0;
    }
    

      

     欢迎讨论交流,qq896250188

    转载于:https://www.cnblogs.com/rmdmn/p/11211472.html

    展开全文
  • 本程序通过期货公司的CTP接口API,将指定合约的TICK行情数据实时接收下来,并保存成文本文件格式。这些数据非常有利于程序交易者进行历史回测。 任何期货投资者都可通过此软件来得到最新的期货行情明细数据,再也不...
  • 本程序通过期货公司的CTP接口API,将指定合约的TICK行情数据实时接收下来,并保存成文本文件格式。这些数据非常有利于程序交易者进行历史回测。 任何期货投资者都可通过此软件来得到最新的期货行情明细数据,再也不...
  • 举个例子,交易数据可以想象成一条河流,Tick就是这条河流在某个截面的数据。国内期货最细粒度就是每秒两次。也就是说国内期货500毫秒最多发送一个Tick。 国内大多数软件是怎么获取Tick的? 那么500毫秒内实际上发生...

    什么是Tick?

    举个例子,交易数据可以想象成一条河流,Tick就是这条河流在某个截面的数据。国内期货最细粒度就是每秒两次。也就是说国内期货500毫秒最多发送一个Tick。

    国内大多数软件是怎么获取Tick的?

    那么500毫秒内实际上发生的成交往往多于一次,里面具体什么情况完全是个黑盒子。特别在商品期货高频交易策略中,Tick行情的接收速度对策略的盈利结果有着决定性的影响。 而市面上大多数交易框架,都是采用回调模式的机制,也就是500毫秒最多只有一个Tick,这还是理想状态。真实情况下onBar/onTick,Tick不漏掉就不错了。为什么呢?因为onBar/onTick函数里面,你要处理一整遍代码逻辑,很浪费时间,不管你愿不愿意,你的策略逻辑必须被打断,必须采用状态机的模式,比如:

    更为先进的机制

    发明者量化交易平台并没有采用这种落后的回调机制,而是采用了不打断策略逻辑的main函数入口机制,让用户可以更自然的控制策略流程。用C++与Golang做为稳定的策略低层,策略上层用Javascript/Python处理逻辑问题。结合事件触发机制,同样的也能使策略在第一时间最快的速度处理行情。 不要说脚本语言速度慢,除非你用它来做神经网络训练,就算用神经网络训练, 加入Jit热编译后,他在任何场合都够用的了, Chrome秒IE十条街就是例子。入门级的策略这里就不再写了, 就以期货高频Tick的合成来说。 比如我们连接一个期货公司,只能收到这个期货公司的行情,我们接收行情的速度跟质量也跟自己的网络有关系,跟期货公司前置机的负载也有关系,那么,怎么样才能做到更快的获取更准确的期货Tick数据呢? 在发明者的策略模型下,你很容易就能操作N家不同期货公司的账户,并把他们的行情,融合处理,以最快的速度下单。正常情况下,我们最多可以从期货公司拿到两个Tick每秒,但通过融合行情的技术,以MA801为例,我们可以拿到最多一秒6次不重复的Tick。

    代码演示

    废话不多说,直接上代码(此代码只能实盘,不能回测,如果您不用发明者可以只参考原理):实盘添加交易所时,可以添加N个期货公司,进行行情的并发融合处理。这里暂时添加两个,演示说明:

    代码如下:

    演示效果

    如上图,可以看到21:24:44秒的时候第一个期货公司的数据比第二个先到,添加两个期货公司就看出来效果了,如果添加5个以上期货公司一起融合。 那么你基本上没有漏Tick的可能,如果用来开发高频交易策略,你已经解决了很重要也是决定性的一步,Tick接收的速度以及稳定性。

    转载自宽客在线 quant.la,原文链接: quant.la/Article/Vie…

    展开全文
  • 中金所Level2股指期货高频历史分笔快照五档tick每月数据包括中国金融期货交易所IH、IC、IF的所有合约,数据有五档委托。在0.5秒内有成交就记录成交,没有成交如果委托盘有变化,就会记录委托档的变化。 数据下载于...
  • 2020.6.10~2020.7.24 期货全市场行情数据 链接:https://pan.baidu.com/s/1AUIMnJFH1SmIdngABSPqcw 提取码:nasu 2020.5.18~2020.6.10 期货全市场行情数据 链接:https://pan.baidu.com/s/11RC7OjhX25_FX0AhhL3VoQ ...

    VNPY官网

    http://www.vnpy.cn

    2020.6.10~2020.7.24 期货全市场行情数据
    链接:https://pan.baidu.com/s/1AUIMnJFH1SmIdngABSPqcw
    提取码:nasu

    2020.5.18~2020.6.10 期货全市场行情数据
    链接:https://pan.baidu.com/s/11RC7OjhX25_FX0AhhL3VoQ
    提取码:lbqq

    2020.4.15~2020.5.17 期货全市场行情数据
    链接:https://pan.baidu.com/s/1tDkL2DSR458OZyzh-nvMNA
    提取码:x22v

    2020.3.18~2020.4.14 期货全市场行情数据
    链接:https://pan.baidu.com/s/1Jj0sTHMn38lQnOFNPBETYA
    提取码:sdke

    2020.2.17~2020.3.17期货全市场行情数据
    链接:https://pan.baidu.com/s/1xsgY39YXt_PENxRaJczB0A
    提取码:b5n0

    2019.12.30~2020.2.14期货全市场行情数据
    链接:https://pan.baidu.com/s/1g_ZmpDGlEs4ewNohNgIpzw
    提取码:zhyc

    2019.11.22~2019.12.27期货全市场行情数据
    https://pan.baidu.com/s/18U0t9qF9ggUkB7nwRfQSaA

    2019.11.1~2019.11.19 期货全市场行情数据
    https://pan.baidu.com/s/1wXBrX8rTL9v4NrdSM6Dbxg

    2019.10.8~2019.10.31期货全市场行情数据
    https://pan.baidu.com/s/1mDZwiOEelqkPidf36wwu8Q

    2017.8.23~2019.9.30期货全市场行情数据
    https://pan.baidu.com/s/17Cs_Md8bAT4cCFzdCapqBQ

    2017.7 ~2019.8.1期货全市场行情数据
    https://pan.baidu.com/s/1TF-6tqLo89v7OstEbxPyLQ

    Virtualapi (CTP 本地TICK级仿真回测接口)
    http://www.virtualapi.cn

    期货实盘低佣金开户,支持CTP接口
    http://www.kaihucn.cn/

    量化代码资源打包下载
    http://mdshare.cn/source.zip
    量化资源
    http://www.coolquant.cn
     

    分7个目录2017.11~2019.5期货全品种TICK数据解压后300Gb(DataCollect格式)百度网盘下载
    期货TICK数据下载
    链接:https://pan.baidu.com/s/1VEp-6Okaqpyj-peGQdE_Ow
    提取码:2bqh

    2018.11.30~2019.1.31期货全品种TICK数据解压后33Gb (DataCollect格式)百度网盘下载
    https://pan.baidu.com/s/1AkdR4tYsg7moqP03VBxx2w

    https://pan.baidu.com/s/1iUgsBvEHpf44-zI6528PSQ
    2012年期货全品种TICK数据
    https://pan.baidu.com/s/1Ta44lVsZG0Qp4Mv8u3g02Q
    2013年期货全品种TICK数据
    https://pan.baidu.com/s/1CUG-oiyV1ksM32sy8w6FyQ
    2014年期货全品种TICK数据
    https://pan.baidu.com/s/1SXeZXQp4ZF6i0Hl8kWETaQ
    2015年期货全品种TICK数据
    《量化交易资源导航》


    http://www.pythonpai.cn

    《程序化交易工具打包下载》
    http://www.pythonpai.com/topic/8/%E7%A8%8B%E5%BA%8F%E5%8C%96%E4%BA%A4%E6%98%93%E5%B7%A5%E5%85%B7%E6%89%93%E5%8C%85%E4%B8%8B%E8%BD%BD

    《做程序化交易,你真的需要数据库吗?》
    http://www.pythonpai.com/topic/181/%E5%81%9A%E7%A8%8B%E5%BA%8F%E5%8C%96%E4%BA%A4%E6%98%93-%E4%BD%A0%E7%9C%9F%E7%9A%84%E9%9C%80%E8%A6%81%E6%95%B0%E6%8D%AE%E5%BA%93%E5%90%97

    vnpy
    http://www.vnpy.cn

     

    期货CTP行情实时采集工具_VNPY官网

    期货CTP行情实时采集工具_VNPY官网

     

    数据同时支持Virrtualapi
    VirtualApi 期货CTP TICK级本地量化交易仿真回测首页 :
    http://www.virtualapi.cn

     



    期货实盘低佣金开户,支持CTP接口, 正规期货公司商品期货低佣金开户(宏源期货、东方期货、华安期货) :

    分7个目录2017.11~2019.5期货全品种TICK数据解压后300Gb(DataCollect格式)百度网盘下载
    期货TICK数据下载

    https://pan.baidu.com/s/1VEp-6Okaqpyj-peGQdE_Ow
    提取码:2bqh


    2018.11.30~2019.1.31期货全品种TICK数据解压后33Gb (DataCollect格式)百度网盘下载
    https://pan.baidu.com/s/1AkdR4tYsg7moqP03VBxx2w
    https://pan.baidu.com/s/1iUgsBvEHpf44-zI6528PSQ
    2012年期货全品种TICK数据
    https://pan.baidu.com/s/1Ta44lVsZG0Qp4Mv8u3g02Q
    2013年期货全品种TICK数据
    https://pan.baidu.com/s/1CUG-oiyV1ksM32sy8w6FyQ
    2014年期货全品种TICK数据
    https://pan.baidu.com/s/1SXeZXQp4ZF6i0Hl8kWETaQ
    2015年期货全品种TICK数据

     

     

    展开全文
  • CTP行情 tick数据免费接收程序

    热门讨论 2014-01-02 19:57:41
    本程序通过期货公司的CTP接口API,将指令合约的TICK行情数据实时接收下来,并保存成文本文件格式。这些数据非常有利于程序交易者进行历史回测。 任何期货投资者都可通过自己的帐号免费得到最新数据,再也不需花大价...
  • tick数据生成K线数据 计算RSI

    千次阅读 2018-04-04 17:09:32
    数据来源大富翁期货数据,文件存放示例 F:\share\zc\20180108\ZC805_20180108.csv F:\share\zc\20180109\ZC805_20180109.csv 以下 代码生成1分钟、5分钟、15分钟k线数据,包括RSI数据示例:大富翁数据中心_市场代码...
  • 本程序通过期货公司的CTP接口API,将指定合约的TICK行情数据实时接收下来,并保存成文本文件格式。这些数据非常有利于程序交易者进行历史回测。 任何期货投资者都可通过此软件来得到最新的期货行情明细数据,再也不...
  • 《《编程小白到量化宗师之路---高频交易系统编写---期货CTP高频数据Tick下载》是上述课程的拆分课程,便于同学们自己针对性选择学习。 本可能涵盖C++环境安装 cmake, VS2019,从现在上期技术的CTP API直到编写行情...
  • 对于一次完整的交易来说,大致可有三个步骤:接收行情-->分析行情(策略部分)-->发出买卖指令并成交(算法交易部分)。可以看出,行情数据是最为基本也是相当...在股票和期货市场上,有level 1行情数据和lev...
  • 中国期货ctp数据自动下载器 制作了一个docker镜像可以更方便的下载tick数据了 中国期货ctp数据自动下载docker
  • 基于LSTM的期货微观市场的趋势预测模型,袁祥枫,代根兴,本文介绍了期货市场的微观结构与LSTM算法的工作原理,并尝试将LSTM应用在期货tick数据上,提出了一个基于LSTM的期货tick数据短期趋势分�
  • 期货数据服务器使用期货、期权tick数据接收软件在共享内存中提供的tick数据,实时生成k线,并且给客户端提供无缝数据服务。 功能如下: 1、合约属性。 2、合约指数表。 3、合约主力表。 4、可交易合约。 5、...
  • 从编程小白到量化宗师之路---期货CTP高频数据Tick下载(含穿透式监管,包含全部C++源代码) ...
  • 课程内容从常用的C++开发技术讲起,到期货tick数据采集,k线生成,下单及策略撰写,从0到1实现一套可实盘的量化交易系统。 课程注重实战,学员上课后,可以达到:日常进行的数据收集,撰写量化策略,实盘交易。 &...
  • (A)Quicklib CTP期货行情交易接口Python开源框架 (C)QuickLib(A股基金指数行情库 例子源代码)MD ...2013~2015期货TICK数据下载 GIT下载最新版本同步到硬盘的工具下载 Python安装环境下载 Quciklib动画和视频教学下载
  • 从编程小白到量化宗师之路C01---股票数据采集和日常维护》是从上述课程中拆分出来的细分课程,便于同学有针对性的选择学习 后续更新:提供中国期货市场历史tick以及1分钟线,5分钟线,日线数据下载。
  • 《日内高频交易实战,从python数据分析到C++编写策略》是《从编程小白到量化宗师... 期货tick数据收集整理课程 https://edu.csdn.net/course/detail/24783 课件中包含一些数据,当然同学们也可以使用自行收集的数据。
  • 实时期货tick数据收集整理课程 https://edu.csdn.net/course/detail/24783 BackTrader基础 https://edu.csdn.net/course/detail/24721 课件中包含一些数据,当然同学们也可以使用自行收集的数据。
  • 对于期货平台搭建来说,其期货系统的功能和工作原理对于开发人员来说很是重要,...1)接受行情服务端推送的行情数据、并按照一定规则过滤掉失真行情数据,并按照一定业务逻辑整理成客户可以使用的行情tick数据和组合...

空空如也

空空如也

1 2 3 4 5
收藏数 91
精华内容 36
关键字:

期货tick数据