基于金字塔平台下开发C++交易策略

Discussion in '金字塔决策交易系统' started by ytweiwei, May 7, 2012.

  1. 我们很多专业投资者及一些投资机构都喜欢使用C++直接编写交易策略,C++语言无论是灵活性和安全性都是要比传统的一般意义上的脚本语言要强大许多,这也是大家所普遍采用的一个主要理由。但是直接使用C++开发需要3个主要组件,主要包括:

    1、历史行情数据的管理和接收

    2、交易策略的评估与实现

    3、下单交易具体实施

    实际上上述3点其实已经包含了一个程序化交易软件所具有的主要特点了,如果是全部都要重新开发一套这样的产品,我们的投资公司最后都要变成名副其实软件公司了,将耗费很大的精力与财力来组织和管理整个软件开发团队。

    如果使用金字塔平台进行C++的策略编写,那么上述的多个难点就可以很好的得到解决,主要如下:

    1、金字塔为C++接口提供了丰富完善的历史数据,包括盘中即时数据,1分,5分,15,30,日线等等多大十几种周期数据,这些数据都是金字塔软件统一管理,模型的开发者不必再来操心历史数据如何管理。

    2、我们的交易策略在前期模型阶段可以利用金字塔平台PEL语言快速的进行评估,评估结束后,再集中精力来变成C++的具体交易算法,节省了大量的时间。

    3、可以利用金字塔平台进行全球市场交易;虽然现在CTP平台开放了交易接口,但毕竟是只有这一个接口,如果交易者要对其他的交易接口例如金仕达、恒生接口等等时,都必须要去重新开发接口,同样是要花费很大的精力。但如果使用金字塔平台,开发者就不必再去关心不同的交易接口到底有哪些不同,我们都已经为客户封装好了统一的交易接口规范,你只要交易策略编写完毕后,就可以在金字塔所支持的国内期货公司,证券公司,外盘期货外汇等等平台上进行交易。
    综上所述,实际上很多底层的服务模块金字塔都已经为客户开发好了,客户在金字塔上只需要关心如何用C++编写策略就可以,极大的加快了投资者的开发周期,并节省了大量的研发费用。

    如何在金字塔上进行C++策略的开发呢

    有关插件接口更详细的描述,在金字塔的安装目录AddinDemo.rar 压缩文件内包含了完整插件接口的接口示例以及在.H头文件里的接口使用信息描述。
    客户也可以点击 http://www.weistock.com/download/addindemo.rar 下载到本地进行学习.
    其中主要的部分都在.H头文件中,我们这里贴出来给大家

    #if !defined(__ADDININTERFACE_H__)
    #define __ADDININTERFACE_H__

    #define STKLABEL_LEN 10 // 股号数据长度,国内市场股号编码兼容钱龙
    #define STKNAME_LEN 32 // 股名长度

    #pragma pack (push ,1)

    /* time_t在金字塔的定义是32位,对于使用VS2005等高版本Visual C++,time_t是64位,直接使用将导致数据结构紊乱
    请在stdafx.h文件里加上如下这个定义即可。#define _USE_32BIT_TIME_T */

    //动态行情数据结构
    typedef struct
    {
    time_t m_time; // 成交时间

    float m_fLastClose; // 昨收
    float m_fOpen; // 今开
    float m_fHigh; // 最高
    float m_fLow; // 最低
    float m_fNewPrice; // 最新
    float m_fOI; //open interest
    float m_fLastOI;
    float m_fVolume; // 成交量
    float m_fAmount; // 成交额

    float m_fLastOpen; //前开
    float m_fLastHigh; //前高
    float m_fLastLow; //前底

    float m_fBuyPrice[3]; // 申买价1,2,3
    float m_fBuyVolume[3]; // 申买量1,2,3
    float m_fSellPrice[3]; // 申卖价1,2,3
    float m_fSellVolume[3]; // 申卖量1,2,3

    float m_fBuyPrice4; // 申买价4
    float m_fBuyVolume4; // 申买量4
    float m_fSellPrice4; // 申卖价4
    float m_fSellVolume4; // 申卖量4

    float m_fBuyPrice5; // 申买价5
    float m_fBuyVolume5; // 申买量5
    float m_fSellPrice5; // 申卖价5
    float m_fSellVolume5; // 申卖量5

    float m_fVolumeNow; //现手
    float m_fBuyVol; //外盘量
    float m_fSellVol; //内盘量
    char m_szName[32]; // 股票名称,以'\0'结尾
    char m_szNamePY[16];
    char m_szLabel[10]; // 股票代码,以'\0'结尾
    float m_f5DayAverage; //5日均量
    float m_fNext5DayVol; //下一个5日均量
    time_t m_timeHardenSpeed; //涨速前比较时间
    float m_fHardenSpeed; //涨速用变量,记录前5分钟价格
    WORD m_wMarket; //品种所属市场比如上海'HS',深圳'ZS'
    }REPORT_STRUCT;

    //日线数据
    typedef struct
    {
    DATE m_timeDate; //UCT
    float m_fOpen; //开盘
    float m_fHigh; //最高
    float m_fLow; //最低
    float m_fClose; //收盘
    float m_fOI; //open interest
    float m_fVolume; //量
    float m_fAmount; //额
    WORD m_wAdvance; //涨数,仅大盘有效
    WORD m_wDecline; //跌数,仅大盘有效
    WORD m_wQT; //成交笔数
    float m_fOpenVolume; //开盘量
    float m_fOpenAmount; //开盘额
    }HISTORY_STRUCTEx;

    //分笔成交数据结构
    typedef struct{
    time_t m_time; // UCT
    float m_fNewPrice;
    float m_fOI; //open interest
    float m_fVolume;
    float m_fAmount;
    unsigned m_bOrder : 1; //成交方向 1买盘 0卖盘
    }SUBSECTION_REPORT;

    //除权信息
    typedef struct
    {
    DATE m_timeDate; // UCT
    double m_fGive; // 每10股送
    double m_fPei; // 每10股配
    float m_fGiveStock; // 实际送股
    float m_fPeiStock; // 实际配股
    float m_fPeiPrice; // 配股价,仅当 m_fPei!=0.0f 时有效
    float m_fProfit; // 每10股红利
    float m_fZhiJieStock; // 直接上市(万股)
    }POWER_STRUCTEx;

    typedef struct {
    WORD m_nMarket;
    char m_szLable[10];
    }BLOCK_STRUCT;

    ////////////////////////////////////////////////////
    //分析周期
    ////////////////////////////////////////////////////
    enum CYC_DATA_TYPE
    {
    MIN1_DATA=0, //1分钟线
    MIN5_DATA, //5分钟线
    MIN15_DATA, //15分钟线
    MIN30_DATA, //30分钟线
    MIN60_DATA, //60分钟线
    DAY_DATA, //日线
    WEEK_DATA, //周线
    MONTH_DATA, //月线
    YEAR_DATA, //年线
    MULTIDAY_DATA, //多日线
    TICK_DATA, //分笔成交
    MULTIHOUR_DATA, //多小时线
    MULTISEC_DATA, //多秒线
    MULTIMIN_DATA, //多分钟线
    QUARTER_DATA, //季度线
    SEMIYEAR_DATA, //半年线
    SOLARTERM_DATA, //节气线
    MIN3_DATA, //3分钟线
    MIN10_DATA, //10分钟线
    MULTITICK_DATA //多笔
    };

    typedef struct
    {
    //////////////////////////////////////////////////////////////////////////
    //调用数据信息
    DWORD m_dwVersion; //调用软件版本(V2.10 : 0x210)
    DWORD m_dwSerial; //调用软件序列号
    char m_szLabel[10]; //调用的品种代码
    WORD m_wMarket; //调用的品种市场,比如上海为'HS'
    CYC_DATA_TYPE m_dataType; //调用数据类型
    BOOL m_bIsPow; //是否复权
    int m_nPowType; //复权类别 0向前复权 1向后复权
    BOOL m_bIsReversePrice; //是否反转价格

    //////////////////////////////////////////////////////////////////////////
    //以下为返回的数据信息
    int m_nNumData; //数据数量
    HISTORY_STRUCTEx * m_pMainData; //主数据缓冲区

    SUBSECTION_REPORT * m_pSubsection; //当日分笔成交明细
    int m_nNumSubData; //分笔数据量

    REPORT_STRUCT* m_pReport; //动态实时行情结构
    float* m_pfFinData; //财务数据

    POWER_STRUCTEx* m_pSplitData; //除权数据
    int m_nNumSplitData; //除权次数
    }PCALCINFO;

    typedef struct tagRCV_REPORT_STRUCTExV3
    {
    WORD m_cbSize; // 结构大小
    time_t m_time; // 成交时间
    WORD m_wMarket; // 股票市场类型
    char m_szLabel[STKLABEL_LEN]; // 股票代码,以'\0'结尾
    char m_szName[STKNAME_LEN]; // 股票名称,以'\0'结尾

    float m_fLastClose; // 昨收
    float m_fOpen; // 今开
    float m_fHigh; // 最高
    float m_fLow; // 最低
    float m_fNewPrice; // 最新
    float m_fVolume; // 成交量
    float m_fAmount; // 成交额

    float m_fBuyPrice[3]; // 申买价1,2,3
    float m_fBuyVolume[3]; // 申买量1,2,3
    float m_fSellPrice[3]; // 申卖价1,2,3
    float m_fSellVolume[3]; // 申卖量1,2,3

    float m_fBuyPrice4; // 申买价4
    float m_fBuyVolume4; // 申买量4
    float m_fSellPrice4; // 申卖价4
    float m_fSellVolume4; // 申卖量4

    float m_fBuyPrice5; // 申买价5
    float m_fBuyVolume5; // 申买量5
    float m_fSellPrice5; // 申卖价5
    float m_fSellVolume5; // 申卖量5
    } RCV_REPORT_STRUCTExV3;
    typedef struct {
    BLOCK_STRUCT m_stStock; //单品种合约
    BYTE m_nBuySell; //0 买入方向 1卖出方向
    WORD m_nVol; //下单数量
    }TAOLI_INFO;

    //成交回报消息结构
    typedef struct {
    long m_nOrderID; //订单ID
    CString m_strStatus; //状态(详见.CPP文件描述)
    long m_nFilled; //已成交数量
    long m_nRemaining; //剩余数量
    float m_fPrice; //成交价格
    CString m_strCode; //品种
    CString m_strMarket; //市场
    BYTE m_nKaiping; //开平仓 0开仓 1平仓
    BYTE m_nType; //订单类型 0限价 1市价 2停损 3限价停损
    BYTE m_nAspect; //买卖方向 0买入 1卖出
    CString m_strAccount; //操作账户
    BYTE m_nAccountType; //账户类型 0IB 1CTP 2金仕达 3股票FIX 4恒生期货
    }BARGAIN_NOTIFY_KSI;

    //////////////////////////////////////////////////////////////////////////
    //消息包结构
    //////////////////////////////////////////////////////////////////////////
    typedef struct {
    RCV_REPORT_STRUCTExV3 * m_pData;
    int m_nDataCount;
    }REPORT_UPDATE1;

    typedef struct {
    RCV_REPORT_STRUCTExQH * m_pData;
    int m_nDataCount;
    }REPORT_UPDATE2;

    #pragma pack (pop)

    //主程序暴露给插件的接口
    interface IMainFramework
    {
    public:
    IMainFramework(){};
    virtual ~IMainFramework(){};

    //取得主窗口句柄
    virtual HWND GetMainWindow() = 0;

    //取主程序版本号
    virtual DWORD GetVersion() = 0;

    //取指定品种数据,成功取得数据返回TRUE,否则为FALSE
    virtual BOOL GetDataInfo(PCALCINFO * pInfo) = 0;

    //取指定品种的动态及时报表
    virtual REPORT_STRUCT * GetReportData(char * szLabel, WORD wMarket) = 0;

    //取指定分类板块的品种数组
    //szName为分类或者板块名称,如"上海A股"等,nMode为类别,0市场分组,1分类板块,2系统板块(品种栏对应)
    virtual void GetReportData(CArray<BLOCK_STRUCT, BLOCK_STRUCT&> &arBlcok, char * szName, int nMode) = 0;

    //注册品种到数据通知,例如RegReportNotify("CL05",'MN');将合约注册到数据通知,当CL05有最新数据到达时触发ReportNotify事件。
    virtual BOOL RegReportNotify(char * szLabel, WORD wMarket) = 0;

    //取消品种数据注册,例如UnRegReportNotify("CL05",'MN'),CL05数据到达时不会再收到通知。
    virtual void UnRegReportNotify(char * szLabel, WORD wMarket) = 0;

    //下单委托交易
    // nType 下单类型 0限价 1市价 2停损 3限价停损
    // fLmtPrice 委托限价
    virtual long PlaceOrder(BYTE nType, float fLmtPrice, float fStopLmtPrice, UINT nVol, BYTE nAspact, LPCSTR lpszLabel, WORD wMarket,
    BOOL bMustOK, LPCSTR lpszAccount, BYTE nKaiPing, BYTE nTouBao, BYTE bOrderQueue) = 0;

    //撤单
    virtual void OrderCancel(long nOrderID, BYTE bOrderQueue) = 0;

    //注册WINDOWS窗口消息,金字塔将以事件方式通知各种
    virtual void RegisterMsg(HWND hMsgWnd, DWORD dwMsg) = 0;

    //得到套利合约信息
    //返回TRUE表示成功 ,返回套利指数内定义的套利品种信息
    virtual BOOL GetTaoliInfo(char * szTaoliLabel, CArray<TAOLI_INFO,TAOLI_INFO&> &m_arTaoliInfo) = 0;

    //得到IB品种持仓数量
    virtual int GetHolding() = 0;

    //得到国内期货的持仓数量
    virtual int GetHolding2(char * szAccount) = 0;

    //到所有IB帐户当前有效的未成交合约品种数量
    virtual int GetOrderNum() = 0;

    //得到所有国内期货当前有效的未成交合约品种数量
    virtual int GetOrderNum2() = 0;

    //得到IB帐户的成交明细数量
    virtual int GetTradeCount() = 0;

    //得到指定帐户的国内期货帐户的成交明细数量
    virtual int GetTradeCount2(CString Account) = 0;

    //当前已经登陆IB顾问帐户子帐户数量,若登陆的是IB普通帐户此属性为1
    virtual int GetIBACCount() = 0;

    //当前已经登陆其他帐户(CTP,金仕达,恒生,股票接口等)数量(包含无效登陆等情况在内的)
    virtual int GetCTPAcCount() = 0;

    //得到当前默认帐户信息
    virtual VARIANT GetAccount(short nType) = 0;

    //得到指定的国内期货帐户信息
    virtual VARIANT GetAccount2(short nType, char * szAccount) = 0;

    /*取指定索引的持仓IB合约信息
    Index 输入参数,指定基于0索引的持仓和约信息,持仓和约总量参见 Holding 属性。
    Hold 输出参数,该该持仓品种持仓量,若空仓返回负数
    MktPrice 输出参数,该持仓品种市价
    AvgPrice 输出参数,该持仓品种均价
    MktValue 输出参数,该持仓品种市值
    AgeCost 输出参数,该持仓品种成本
    PNL 输出参数,该持仓品种浮动盈亏
    Code 输出参数,该持仓品种代码
    Market 输出参数,该持仓品种市场
    返回值: 成功返回1,失败返回0 */
    virtual BOOL HoldingInfo(UINT Index, int &Hold, double &MktPrice, double &AvgPrice, double &MktValue, double &AgeCost, double &PNL, CString &Code, WORD &Market) = 0;

    /*取指定索引的指定其他帐户(CTP,金仕达,恒生,股票接口等)的合约持仓信息
    Index 输入参数,指定基于0索引的持仓和约信息,持仓和约总量参见 Holding2 属性。
    BuyHoding 输出参数,该该持仓品种买入持仓总量
    BuyCost 输出参数,该持仓品种持仓成本
    BuyTodayHoding 输出参数,该持仓品种今买持总量
    SellHoding 输出参数,该持仓品种卖出持仓总量
    SellCost 输出参数,该持仓品种卖出持仓成本
    SellTodayHoding 输出参数,该持仓品种的今卖出持仓总量
    PNL 输出参数,该持仓品种浮动盈亏
    UseMargin 输出参数,该持仓品种的保证金占用
    Code 输出参数,该持仓品种代码
    Market 输出参数,该持仓品种市场
    Account 输入参数,可缺省,登陆其他帐户(CTP,金仕达,恒生,股票接口等)名称,若不填写则表示当前默认的帐户
    返回值: 成功返回1,失败返回0 */
    virtual BOOL HoldingInfo2(UINT Index, int &BuyHoding, double &BuyCost, int &BuyTodayHoding, int &SellHoding, double &SellCost, int &SellTodayHoding, double &PNL, double &UseMargin, CString &Code, WORD &Market, CString Account) = 0;

    /*
    * 取指定基于0索引的未成交IB合约信息
    Index 输入参数,指定基于0索引的持仓和约信息,持仓和约总量参见 OrderNum 属性。
    OrderID 输出参数, 未成交订单ID
    ConSign 输出参数,本次委托数量
    Filled 输出参数,已成交数量
    Remaining 输出参数,未成交数量
    Action 输出参数,动作类型 0买入 1卖出
    OrderType 输出参数,订单类型 0限价 1市价 2停损 3市价停损
    LmtPrice 输出参数,当OrderType等于0时为限价,为3时为停损限价
    auxPrice 输出参数,停损价格
    Account 输出参数,帐户信息
    Code 输出参数,该持仓品种代码
    Market 输出参数,该持仓品种市场
    返回值: 成功返回1,失败返回0
    */
    virtual BOOL OrderInfo(UINT Index, int &OrderID, int &ConSign, int &Filled, int &Remaining, int &Action, int &OrderType, double &LmtPrice, double &auxPrice, CString &Account, CString &Code, WORD &Market) = 0;

    /*取指定基于0索引的未成交其他帐户(CTP,金仕达,恒生,股票接口等)合约信息
    Index 输入参数,指定基于0索引的持仓和约信息,持仓和约总量参见 OrderNum2 属性。
    OrderID 输出参数, 未成交订单ID
    ConSign 输出参数,本次委托数量
    Filled 输出参数,已成交数量
    Remaining 输出参数,未成交数量
    Action 输出参数,动作类型 0买入 1卖出
    OrderType 输出参数,订单类型 0限价 1市价 2停损 3市价停损
    LmtPrice 输出参数,当OrderType等于0时为限价,为3时为停损限价
    Account 输出参数,帐户信息
    Kaiping 输出参数,开平仓类型 0开仓 1平仓
    Code 输出参数,该持仓品种代码
    Market 输出参数,该持仓品种市场
    返回值: 成功返回1,失败返回0 */
    virtual BOOL OrderInfo2(UINT Index, int &OrderID, int &ConSign, int &Filled, int &Remaining, int &Action, int &OrderType, double &LmtPrice, CString &Account, int &Kaiping, CString &Code, WORD &Market) = 0;

    /*获取指定品种的合约种类
    Code 输入参数,指定的品种代码
    Market 输入参数,指定的品种市场
    返回值:是可以交易的国内期货接口品种返回1,IB接口返回0*/
    virtual int StockType(char * szCode, WORD wMarket) = 0;

    /*取指定品种的和约信息
    Code 输入参数,指定的品种代码
    Market 输入参数,指定的品种市场
    Multipliter 输出参数,该品种的乘数/单位
    MinTick 输出参数,该品种的最小变动单位
    ShortPercent 输出参数,该品种的空头保证金
    LongPercent 输出参数,该品种的多头保证金
    返回值:成功返回1否则返回0
    */
    virtual int GetContract(char *szCode, WORD wMarket, float &Multipliter, float &MinTick, float &ShortPercent, float &LongPercent) = 0;

    /*计算指定品种的本次交易手续费用。请用户在交易费率设置上预先设置好不同品种的各种交易费率情况,这样才能通过此方法得到正确的结果。
    Code 指定的品种代码
    Market 指定的品种市场
    lmtPrice 指定的限价
    Volume 委托数量
    Type 成交方向 0买入 1卖出
    返回值: 返回计算后的手续费用*/
    virtual float GetChargeByNum(char * szCode, WORD wMarket, float lmtPrice, int Volume, int Type) = 0;

    /*取指定基于0索引序号的IB帐户成交明细
    Index 输入参数,基于0索引的成交明细
    Date 输出参数,成交时间
    Code 输出参数,品种代码
    Market 输出参数,品种市场
    OrderType 输出参数,成交单类型,0限价 1市价 2停损 3限价停损
    Action 输出参数,成交方向 0买入 1卖出
    Price 输出参数,成交价格
    Volume 输出参数,成交量
    Account 输出参数,成交帐户
    返回值: 成功返回1,失败返回0*/
    virtual int TradeDetalied(int Index, DATE &Date, CString &Code, WORD &Market, int &OrderType, int &Action, float &Price, int &Volume, CString &Account) = 0;

    /*取指定基于0索引序号的其他帐户(CTP,金仕达,恒生,股票接口等)成交明细
    Index 输入参数,基于0索引的成交明细
    Date 输出参数,成交时间
    Code 输出参数,品种代码
    Market 输出参数,品种市场
    OrderType 输出参数,成交单类型,0限价 1市价 2停损 3限价停损
    Action 输出参数,成交方向 0买入 1卖出
    Price 输出参数,成交价格
    Volume 输出参数,成交量
    Kaiping 输出参数,开平仓类型,0开仓 1平仓
    Account 输入参数,成交帐户,可省略,若省略则表示当前默认激活帐户
    返回值: 成功返回1,失败返回0*/
    virtual int TradeDetalied2(int Index, DATE &Date, CString &Code, WORD &Market, int &OrderType, int &Action, float &Price, int &Volume, int &Kaiping, CString &Account) = 0;

    //得到指定基于0索引的IB帐户名称,例如IBAccountName(0)表示取第一个登陆的IB帐户
    virtual CString GetIBAccountName(int nIndex) = 0;

    //得到指定基于0索引的其他帐户(CTP,金仕达,恒生,股票接口等)名称(包含登陆未成功的),例如 CTPAccountName(0)表示取第一个登陆的其他帐户(CTP,金仕达,恒生,股票接口等)用户名称
    virtual CString GetCTPAccountName(int nIndex) = 0;

    //判断指定帐号是否是当前已登录有效帐号,例如 Order.IsAccount("351579"),如果该账户已登录则返回1,否则返回0
    virtual int IsAccount(CString strAccount) = 0;
    };

    #endif
    最后请大家注意的就是金字塔下C++插件的扩展名是 *.ADI 文件名,实际上就是DLL程序改了扩展名放到金字塔的工作目录下,这么设计主要是为了与金字塔已有的DLL模块冲突,放倒金字塔工作目录后,重新启动金字塔软件,就会在 工具菜单-》扩展 里看到我们所开发出来的C++插件了。
     
  2. 若不成交,如何撤单并快速重新下单?
     
  3. 对于PEL语言,自动自带自动追单功能,对于C++的底层开发,需要用户自行来处理。
    参考撤单函数 OrderCancel
    下单函数 PlaceOrder
     
  4. 谢谢

    金字塔功能很多,还在学习中
     
  5. 如果希望使用C++开发策略并实盘下单,是否购买标准版就可以了?
     
  6. 需要专业版
     
  7. 恩,金字塔的C语言接口很好用,就是免费的行情服务器太糟糕了。
     
  8. 金字塔功能很多
     
  9. 有BCB6的例程吗?急需!