转自http://blog.csdn.net/hacode/article/details/7065889

编译quickfast解析库(沪深level2行情转码库)

目录(?)[-]
 

为了方便大家编译和使用QuickFast库,我在GitHub上放置了一个v1.4版本的构建环境:

https://github.com/imharrywu/quickfast

包括了预编译的依赖库(boost, xcerces) 以及工程管理的MPC, 同时生成了一个预编译的库在Output\Release下。

说明一下,对1.4的构建环境稍作了修改:

1,使用MPC4.1,因为需要boost_system

2,全部使用了动态库,官方编译的时候,只有boost_thread使用动态库,感觉不太协调,所以统一全部是动态库.

3,需要boost_date_time, boost_chrono等。

详细步骤请直接看GitHub上的README.md

1) 下载源代码

下载quickfast项目(windows平台):

http://quickfast.googlecode.com/files/quickfast_win_src_1_4.zip

公布一个QQ群:229609210 同行们可以申请加入一起讨论。

2) 下载第三方库和配置脚本

 

2.1) 下载activeperl

(google it)

2.2) 下载mpc

http://www.ociweb.com/products/mpc

2.3) 下载boost

(google it)

2.4) 下载xerces

http://xerces.apache.org/xerces-c/

2.5) 配置脚本

下载 行情转码库的配置脚本setup.bat(gif文件另存为zip,解压可以得到bat文件)

http://hi.csdn.net/attachment/201112/13/0_1323743665laAL.gif

setup.bat配置脚本设置三方库路径和编译器选项

  1. @REM 1) Customize this file by setting variables to suit your environment
  2. @REM 2) Also you should customize QuickFAST.features to enable particular features on your system.
  3. @REM 3) Delete the following line when you finishing customizing this file.
  4. @REM           [==DELETED==]echo See remarks in %0 for information about setting your build environment
  5. @REM 4) And, then run the `m.cmd' to generate *.sln & *.vcproj files
  6. @echo off
  7. REM =====================================================================================
  8. REM EDIT THE FOLLOWING LINES OR SET THESE VALUES IN YOUR ENVIRONMENT BEFORE RUNNING SETUP
  9. if "a" == "a%MPC_ROOT%" set MPC_ROOT=H:\workspace\qf\MPC
  10. if "a" == "a%XERCES_ROOT%" set XERCES_ROOT=H:\workspace\qf\xerces-c-3.1.1-x86-windows-vc-8.0
  11. if "a" == "a%XERCES_LIBNAME%" set XERCES_LIBNAME=xerces-c_3
  12. if "a" == "a%BOOST_VERSION%" set BOOST_VERSION=boost_1_47_0
  13. if "a" == "a%BOOST_ROOT%" set BOOST_ROOT=H:\workspace\qf\%BOOST_VERSION%
  14. REM END OF VALUES TO BE SET
  15. REM =====================================================================================

注意:boost默认编译出来的include和lib不在同一个目录下,需要move一下。

3) 生成项目文件

在vc的命令行下,运行这个setup.bat && m.bat就可以生成QuickFast.sln

4) 编译生成QuickFast库

vs2008打开QuickFast.sln编译连接,生成的文件在Output目录的相应配置文件夹下。

5) 样例程序文档

这个解决方案提供了很多例子,最简单的是TutorialApplication和InterpretApplication这2个例子。

也可以用doxygen生成文档。

http://hi.csdn.net/attachment/201112/26/0_1324861393eteG.gif

6) 行情解码例子程序

楼主用Codecs::SynchronousDecoder(同步解码器,官方例子使用的是异步解码器) 实现了一个简单的解码封装DLL,通过tcp socket从上游数据源获取fast的码流并且解码。

同行们你们主要参考  RunDecoderLoop(...)函数内部的行情解码步骤  

这个dll的其他代码都可以忽略, 主要关注 《第七节 行情解码的几个主要步骤》 的内容。

这个例子是一个dll库,导出了一个API,这个API以市场代码等为参数(上海市场解码,或者深圳市场解码),开始各个市场的解码。

同时这个API接受一组回调接口来通知数据消费者来处理解码后的行情数据, 参看 IDataExInterface 定义。

建议大家把2个市场的解码放在2个线程里面,最好分别在2个机房里面。

FAST码流是剥掉了STEP协议头以后STEP协议BODY部分用FAST编码过的内容。

Fast_Steam Fast(STEP_PACKET -STEP_HEAD) =Fast(STEP_BODY)

导出库的头文件

  1. #ifdef __cplusplus
  2. extern "C"
  3. {
  4. #endif
  5. enum MarketTag
  6. {
  7. ShenzhenMarket = 0,
  8. ShanghaiMarket = 1,
  9. };
  1. struct IDataExInterface /*解码以后的数据通过接口中的pNotify接口来通知客户端更新数据*/
  2. {
  3. void (__stdcall * pfnFeedStatus)(ConnectionStatus connStatus);
  4. // 上海的行情数据通知接口
  5. void (__stdcall * pfnFeed_SHFAST30_UA3202)(const SHFAST30_UA3202_t * );
  6. void (__stdcall * pfnFeed_SHFAST30_UA3201)(const SHFAST30_UA3201_t * );
  7. void (__stdcall * pfnFeed_SHFAST30_UA3113)(const SHFAST30_UA3113_t * );
  8. // 深圳的行情数据通知接口
  9. void (__stdcall * pfnFeed_SZFAST_103)(const SZFAST_103_t *);
  10. void (__stdcall * pfnFeed_SZFAST_202)(const SZFAST_202_t *);
  11. void (__stdcall * pfnFeed_SZFAST_201)(const SZFAST_201_t *);
  12. void (__stdcall * pfnFeed_SZFAST_104)(const SZFAST_104_t *);
  13. };
  1. FASTDECODER_API
  2. int RunDecoderLoop(const char * pIp
  3. , unsigned short nPort
  4. , MarketTag nMarketTag
  5. , const char * templateFileName
  6. , const struct IDataExInterface * pNotify
  7. );
  8. #ifdef __cplusplus
  9. };
  10. #endif

客户端可以这样调用DLL

  1. void Level2Thread(void * arg) // 把各个市场的解码放在各自的线程里面
  2. {
  3. MarketTag nMarketTag = static_cast<MarketTag>((int)arg);
  4. IDataExInterface * pNotify = new IDataExInterface;
  5. memset(pNotify, 0, sizeof(IDataExInterface));
  6. pNotify->pfnFeedStatus = FeedStatus; // 用于报告解码状态的回调
  7. switch (nMarketTag)
  8. {
  9. case ShenzhenMarket:
  10. {
  11. SetThreadAffinityMask(GetCurrentThread(), 1);
  12. pNotify->pfnFeed_SZFAST_103         = Feed_SZFAST_103;
  13. pNotify->pfnFeed_SZFAST_104         = Feed_SZFAST_104;
  14. pNotify->pfnFeed_SZFAST_201         = Feed_SZFAST_201;
  15. pNotify->pfnFeed_SZFAST_202         = Feed_SZFAST_202;
  16. RunDecoderLoop( // 在该线程里面开始深圳市场解码
  17. "127.0.0.1", 1111
  18. , MarketTag(ShenzhenMarket)
  19. , ".\\fasttemplates_2.00.xml"
  20. , pNotify);
  21. } break;
  22. case ShanghaiMarket:
  23. {
  24. SetThreadAffinityMask(GetCurrentThread(), 2);
  25. pNotify->pfnFeed_SHFAST30_UA3113    = Feed_SHFAST30_UA3113;
  26. pNotify->pfnFeed_SHFAST30_UA3201    = Feed_SHFAST30_UA3201;
  27. pNotify->pfnFeed_SHFAST30_UA3202    = Feed_SHFAST30_UA3202;
  28. RunDecoderLoop( // 在该线程里面开始上海市场解码
  29. "127.0.0.1", 2222
  30. , MarketTag(ShanghaiMarket)
  31. , ".\\template.2.03.xml"
  32. , pNotify);
  33. } break;
  34. }
  35. return ;
  36. }
  37. /**
  38. *
  39. * 简单的开启两个市场的解码线程开始解码,
  40. * 导出函数RunDecoderLoop是一个循环解码的阻塞调用过程,
  41. * 所以放在2个独立的线程中。
  42. *
  43. **/ int main(int argc, char* argv[])
  44. {
  45. _beginthread(Level2Thread, 0, (void *)ShanghaiMarket);
  46. _beginthread(Level2Thread, 0, (void *)ShenzhenMarket);
  47. printf("Press any key to quit decoder.\n"); getchar();
  48. return 0;
  49. }

7) 行情解码的几个主要步骤

用Codecs::SynchronousDecoder解码fast的几个重要步骤

7.1)  构造xml解析对象

  1. /************************************************************************
  2. *
  3. * 全局的xml解析类
  4. *
  5. * 注意: 多线程同时构造parser会资源冲突
  6. *
  7. *
  8. ************************************************************************/
  9. static Codecs::XMLTemplateParser parser;

7.2) 解析xml模板生成fast模板

  1. /////////////////////////////////////////////
  2. // Parse the templates from the template file
  3. // errors are reported by throwing exceptions
  4. // which are caught below.
  5. std::ifstream tmplFile(templateFileName, openMode);
  6. Codecs::TemplateRegistryPtr registry;
  7. try {
  8. registry = parser.parse(tmplFile);
  9. }catch (std::exception & e){
  10. std::cerr << e.what() << std::endl;
  11. return -1;
  12. }

7.3) 创建一个decoder对象

  1. //////////////////////////////////////
  2. // Create a sync decoder and
  3. // setup attributes.
  4. Codecs::SynchronousDecoder * pDecoder
  5. = new Codecs::SynchronousDecoder(registry);
  6. pDecoder->setHeaderBytes(0);
  7. pDecoder->setResetOnMessage(false);
  8. pDecoder->setLimit(0);

7.4) 实现一个消息消费者,并且注册给解码器

  1. //////////////////////////////////////
  2. // Create an application object to use
  3. // the incoming data.  In this case to
  4. // accept complete messages and interpret
  5. // them to standard out.
  6. CMessageConsumerImpl * pHandler
  7. = new CMessageConsumerImpl(nMarketTag
  8. , pNotify
  9. , pDecoder);
  10. //////////////////////////////////////
  11. // and use the interpreter as the consumer
  12. // of generic messages.
  13. Codecs::GenericMessageBuilder builder(*pHandler);

7.5) 开始解码

接收网络数据包(放置在pFastBody, 长度位nBodyLength)

  1. pDataSource = new Codecs::DataSourceBuffer(pFastBody , pFastHeader->nBodyLength);
  1. try{
  2. pDecoder->reset();
  3. pDecoder->decode(*pDataSource, builder);
  4. } catch (std::exception & e)
  5. {
  6. std::cout<<e.what()<<std::endl;
  7. }
  8. delete pDataSource;
  9. pDataSource = NULL;

7.6)实现消息消费者接口

  1. /// @brief A message consumer that attempts to produce a human readable version
  2. /// of a message that has been decoded by QuickFAST.
  3. class CMessageConsumerImpl : public Codecs::MessageConsumer

重写消费消息函数

  1. virtual bool consumeMessage(Messages::Message & message);

7.7) 消费消息的过程就是消息的格式化过程

在消息的格式化过程中,主要是遍历Message的各个filed,如果field是

一般类型,直接转换成相应的值;如果是sequence和group,则需要将

field转换成sequence和group,遍历;另外,由于sequence里面的每一个

item也是一个Message结构,所以需要以Message的方式遍历结构的每一个成员;

  1. foreach(item in seq)
  2. foreach(member in item)

7.8) 输出

8) 资源下载

=========================================================================

项目源文件下载

(将下面的gif链接另存为zip,解压->重命名->解压,有加密,确实有需要的朋友请留言获取)

=========================================================================

最新版本

version 2.0,修改了日志打印方式和配置文件加载quickfast-v2-[8n0].zip.png

http://hi.csdn.net/attachment/201112/27/0_132498087296Py.gif

历史版本

version 1.0,项目源文件Examples-8n0.zip

http://hi.csdn.net/attachment/201112/26/0_132486187064m4.gif

【转】编译quickfast解析库(沪深level2行情转码库)的更多相关文章

  1. [python]沪深龙虎榜数据导入通达信的自选板块,并标注于K线图上

    将沪深龙虎榜数据导入通达信的自选板块,并标注于K线图上 原理:python读取前一次处理完的计算5日后涨跌幅输出的csv文件 文件名前加"[paint]" 安照通达信的画图文件和板 ...

  2. [python]沪深龙虎榜数据进一步处理,计算日后5日的涨跌幅

    沪深龙虎榜数据进一步处理,计算日后5日的涨跌幅 事前数据: 前面处理得到的csv文件 文件名前加入“[wait]”等待程序处理 python代码从雅虎股票历史数据api获取数据,计算后面5日的涨跌幅 ...

  3. [python]数据整理,将取得的众多的沪深龙虎榜数据整一整

    将昨日取得的众多的沪深龙虎榜数据整一整 提取文件夹内所有抓取下来的沪深龙虎榜数据,整理出沪深两市(含中小创)涨幅榜股票及前5大买入卖出资金净值,保存到csv文件 再手动使用数据透视表进行统计 原始数据 ...

  4. [python]初试页面抓取——抓取沪深股市交易龙虎榜数据

    [python]抓取沪深股市交易龙虎榜数据 python 3.5.0下运行 没做自动建立files文件夹,需要手动在py文件目录下建立files文件夹后运行 #coding=utf-8 import ...

  5. window10(64bit)+VS2010编译ACE_TAO源码库

    1.下载 ACE+TAO下载地址:http://download.dre.vanderbilt.edu/previous_versions/ VS2010下载地址:https://pan.baidu. ...

  6. python量化之路:获取历史某一时刻沪深上市公司股票代码及上市时间

    最近开始玩股票量化,由于想要做完整的股票回测,因此股票的上市和退市信息就必不可少.因为我们回测的时候必须要知道某一日期沪深股票的成分包含哪些对吧.所以我们要把沪深全部股票的上市时间.退市时间全部都爬下 ...

  7. 高级C/C++编译技术之读书笔记(三)之动态库设计

    最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...

  8. 高级C/C++编译技术之读书笔记(四)之定位库文件

    最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...

  9. 【VS工程设置】 编译动态库,命令行添加参数,不使用预编译头,指定该项目链接 哪种 运行库

    编译动态库 注意: 动态库: [目标文件扩展] => .dll + [配置类型] => 动态库(.dll) 静态库: [目标文件扩展] => .lib + [ 配置类型]=> ...

随机推荐

  1. Centos6下rpm安装MySQL5.6

    Centos6在rpm安装 rpm -ivh http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm yum install ...

  2. 7 -- Spring的基本用法 -- 7...

    7.7 创建Bean的3种方式 ① 调用构造器创建Bean. ② 调用静态工厂方法创建Bean. ③ 调用实例工厂方法创建Bean. 7.7.1 使用构造器创建Bean实例. 使用构造器来创建Bean ...

  3. 通过 Informix 系统表监控和优化数据库

    Informix 数据库系统字典表简介 Informix 数据库服务器运行时的状态信息是数据库管理员 DBA 进行系统监控和优化的必需信息来源.Informix 的状态信息在内部以 2 种方式存在,如 ...

  4. NodeJS学习笔记 - Express4.x路由操作

    一.为Express添加about路由 1.新建js文件,about.js 2.打开about.js,并输入以下代码: var express=require('express'); var rout ...

  5. LR参数化后取值规则小记

    对参数化的取值,只有一个用户的情况能分清,但是多用户多迭代就搞不懂,特意使用Parameter List中自带的参数化模拟器Simulate Parameter进行简单的实验,3条数据 + 4个用户 ...

  6. px和em

    相同点: 都是长度单位 不同点: px是绝对单位,不支持IE的缩放,em是相对单位. px的值是固定的,指定是多少就是多少:em得值不是固定的,并且em会继承父级元素的字体大小 ps: 浏览器的默认字 ...

  7. Windows Store App 全球化:引用分离资源文件中的资源

    大部分应用程序仅需要单个默认资源文件,例如Strings/zh-CN/Resources.resw,但是在某些应用程序中,最好将资源分离到多个资源文件中,以便更好地组织资源内容,这样就需要考虑如何引用 ...

  8. 美女程序员是如何将QQ转换成题目中那串数字的--读博文《找女神要QQ号码》

    我只能说好好的端午节你们不约么?,还在这里写代码?我也是够无聊的,下班了不走也在这跟风写着玩!<找女生要QQ号码原文>原文链接http://www.cnblogs.com/iforever ...

  9. 快消零售行业怎么用K2做开关店管理?

    提起迪卡侬,想到的便是它汇聚所有运动于同一个屋檐下的盛况.从来没有一家体育用品零售店可以像迪卡侬一样,涵盖几乎所有级别的运动产品.从入门级到最专业的运动产品,应有尽有,不仅产品质量有保证,价格也平易近 ...

  10. redhat6.4上安装mysql

    1.挂载操作系统介质 [root@server- ~]# mkdir -p /media/dvd [root@server- ~]# -20130130.0-Server-x86_64-DVD1.is ...