#ifndef _STOCK_CONFIG_H_ #define _STOCK_CONFIG_H_ typedef unsigned long ulong; typedef unsigned int uint; typedef unsigned short ushort; typedef unsigned char uchar; #endif
#ifndef _TDX_STOCK_H_ #define _TDX_STOCK_H_ #include "stdafx.h" #include <fstream> #include <set> #include <vector> #include <map> #include "config.h" using namespace std; #define STOCK_CODE_LEN 6 enum PacketType { PKT_TYPE_RESPONSE=0x00, PKT_TYPE_REQUEST=0x01, PKT_TYPE_QUOTES=0x02 }; enum MarketType { MKT_TYPE_SHENZHEN=0x00, MKT_TYPE_SHANGHAI=0x01 }; enum PostFix { POSTFIX_GET_STOCK_COUNT = 0x0133c775 }; enum CmdId { CMD_STOCKHOLD_CHANGE = 0x000f, CMD_STOCK_LIST = 0x0524, CMD_HEART_BEAT = 0x0523, CMD_GET_STOCK_COUNT= 0x044e, CMD_GET_STOCK_QUOTES = 0x053e, CMD_GET_MINUTE_DATA = 0x051d, CMD_GET_HIS_MINUTE_DATA = 0x0fb4, CMD_GET_TRANSACTION_DATA = 0x0fc5, CMD_GET_HIS_TRANSACTION_DATA = 0x0fb5, CMD_GET_INDEX_BARS = 0x052d }; typedef set<string> StringSet; struct MarketInfo { enum MarketType { MARKET_FIRST, MARKET_SHANGHAI_A = MARKET_FIRST, MARKET_SHANGHAI_B, MARKET_SHENZHEN_A, MARKET_SHENZHEN_B, MARKET_WARRANT, // 权证 MARKET_INDEX , // 指数 MARKET_MAX, MARKET_UNKNOWN = MARKET_MAX, }; static char get_block_from_market_type(MarketType t) { switch(t) { case MARKET_SHANGHAI_A: return 0; case MARKET_SHANGHAI_B: return 1; case MARKET_SHENZHEN_A: return 2; case MARKET_SHENZHEN_B: return 3; case MARKET_INDEX: return 11; // 所有指数 case MARKET_WARRANT: return 13; // 权证 default: throw 0; } } static unsigned int stocks_count[MARKET_MAX]; static StringSet stocks_set[MARKET_MAX]; const static int StocksCodeLen = 6; // 100 股一手 const static int StocksPerHand = 100; // 100 股一手. const static float tax; // 0.3 % static short get_market_type_from_code( const char* pCode ) { if ( pCode[0] == '0' ) { if ( pCode[1] == '0' ) return MARKET_SHENZHEN_A; else return MARKET_WARRANT; // 03xxxx } else if ( pCode[0] == '2' ) return MARKET_SHENZHEN_B; else if ( pCode[0] == '3' ) // 3xxxxx return MARKET_INDEX; else if ( pCode[0] == '6' ) return MARKET_SHANGHAI_A; else if ( pCode[0] == '9' ) { if ( pCode[1] == '0' ) return MARKET_SHANGHAI_B; // 90xxxx else return MARKET_INDEX; // 99xxxx } else if ( pCode[0] == '5' ) return MARKET_WARRANT; else return MARKET_UNKNOWN; } static short get_market_type(const char* pCode) { return get_market_type_from_code(pCode); } static short get_market_type( const string& stock_code ) { const char* pCode = stock_code.c_str(); return get_market_type_from_code( pCode ); } static char get_market_location_from_code( const char* pCode ) { if ( pCode[0] <= '4' ) return 0; // 深圳 00xxxx, 03xxxx, 02xxxx, 3xxxxx(深圳指数) else return 1; //上海 60xxxxx, 58xxxx, 99xxxx (上海指数) } static char get_market_location(const char* pCode) { return get_market_location_from_code(pCode); } static char get_market_location(const string& stock_code) { const char* pCode = stock_code.c_str(); return get_market_location_from_code(pCode); } static string get_first_stock(); static string find_next_stock(const string& stock_code); }; class StockTransact { public: struct Transact { short minute; int price; int vol; int count; // 此笔成交量的成交次数。 0: 表示未知 uchar bs; // 表示买成交量还是卖成交量0:buy, 1:sell bool operator == (const Transact& t); template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & minute; ar & price; ar & vol; ar & bs; } }; typedef vector<Transact> DailyTransact; typedef map<string, DailyTransact> DateTransact; typedef map<uint, DateTransact> TransactMap; }; extern StockTransact::DateTransact today_transact; extern StockTransact::TransactMap hist_transact; class StockBid { public: struct Bid // 盘口 { int minute; int act; // 活跃度 active rate int price; // 现价 int y_close; // 昨收 int open; // 开盘 int high; // 最高 int low; // 最低 int buy; // 买入 int sell; // 卖出 int total_vol; // 总手,以股数计算 int avail_vol; // 现手,以股数计算 int inner_vol; // 内盘 int outer_vol; // 外盘 int updown; // 单笔升跌 int buy_price1; // 买价1 int sell_price1; int buy_vol1; // 买量1 int sell_vol1; int buy_price2; int sell_price2; int buy_vol2; int sell_vol2; int buy_price3; int sell_price3; int buy_vol3; int sell_vol3; int buy_price4; int sell_price4; int buy_vol4; int sell_vol4; int buy_price5; int sell_price5; int buy_vol5; int sell_vol5; char stock_code[7]; int update_time; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & minute; ar & act; ar & price; ar & y_close; ar & open; ar & high; ar & low; ar & buy; ar & sell; ar & total_vol; ar & avail_vol; ar & inner_vol; ar & outer_vol; ar & updown; ar & buy_price1; // 买价1 ar & sell_price1; ar & buy_vol1; // 买量1 ar & sell_vol1; ar & buy_price2; ar & sell_price2; ar & buy_vol2; ar & sell_vol2; ar & buy_price3; ar & sell_price3; ar & buy_vol3; ar & sell_vol3; ar & buy_price4; ar & sell_price4; ar & buy_vol4; ar & sell_vol4; ar & buy_price5; ar & sell_price5; ar & buy_vol5; ar & sell_vol5; } }; typedef vector<Bid> DailyBid; typedef map<uint, DailyBid> DateBid; typedef map<string, DateBid> BidMap; }; extern StockBid::BidMap instant_price_list; typedef vector<string> StringVector; struct BaseInfo { string stock_code; uint update_time; double ttl_amount; // 总股本 double state_own_amount; // 国家股 double init_amount; // 发起股本 double corp_amount; // 法人股本 double b_amount; // B 股本 double h_amount; // H 股本 double cir_amount; // 流通 股本 double empl_amount; // 职工 股本 double unknown1; // double ttl_asset; // 总资产 double varible_asset; // 流动 资产 double firm_asset; // 固定 资产 double invisible_asset; // 无形 资产 double long_term_invest; // 长期投资 double varible_debt; // 流动负债 double long_term_debt; // 长期负债 double accu_fund; // 公积金 double net_asset; // 净资产 double major_income; // 主营收入 double major_profit; // 主营利润 double unknown2; // double bussiness_income; // 营业收入 double invest_income; // 营业收入 double allowance; // 补贴收入 double non_bussiness_income; // 业外收入 double income_adjustment; // 收入调整 double ttl_profit; // 利润总额 double unknown3; // double net_profit; // 税后利润 double undist_profit; // 未分配利润 double per_net_assert2; // 每股净资产2 static const int record_len; }; typedef map<string, BaseInfo> StockBaseInfoMap; typedef map<string, StringVector> StockGroupMap; extern fstream& operator >> (fstream& ifs, BaseInfo& bs); typedef map<string, StringVector> StringVectorMap; struct GBBQ { string code; uchar chg_type; // 变更类型 // 1: 正常 // 2: 与1相关的除权除息日股本变化 // 3:股本性质变化(例如职工股上市) // 6: 增发. // 8: 增发上市 union { struct { float cash; // 每10 分红 float sell_price; // 每股配售价格 float give_count; // 每10 股送股数 float sell_count; // 每10 股配售数 }bonus; struct { float old_cir; // 旧流通股 float old_ttl; // 旧总股本 float new_cir; // 新流通股 float new_ttl; // 新总股本 }gb; }data; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & dt; ar & chg_type; ar & data.bonus.cash; ar & data.bonus.sell_price; ar & data.bonus.give_count; ar & data.bonus.sell_count; } }; typedef vector<GBBQ> DateGBBQ; typedef map<uint, DateGBBQ> GBBQMap; class StockBasicInfo { public: bool load_basic_info(); void save_basic_info(); bool load_block_info(); void save_block_info(); void clear_gbbq_info(); // bool load_gbbq_info(gregorian::date start_date, int day_count); void save_gbbq_info(uint tr_date); void save_stock_set(); void add_stock_gbbq(uint dt, const GBBQ& gbbq); string get_gbbq_file_name(uint tr_date); bool is_gbbq_file_exist(uint tr_date); private: StockBaseInfoMap stock_base_info; StockGroupMap stock_block_info; GBBQMap stock_gbbq_info; }; struct QuotePara { uchar cMarket; char sStockCode[6]; }; struct MinuteData { int iPriceRaw; int iReserved1; int iVol; }; struct MatchedData { int iHour; int iMinute; int iPriceRaw; int iVol; int iNum; int iBuyOrSell; int iReserved; }; struct IndexBarsData { int iYear; int iMonth; int iDay; int iHour; int iMinute; int iPriceOpenDiff; int iPriceCloseDiff; int iPriceHighDiff; int iPriceLowDiff; int iVolRaw; int iDbVolRaw; int iUpCount; int iDownCount; }; /// // // Semantic actions // /// extern void show_curr_bid(char const* first, char const* last ); struct ReqTimeInfo { uint m_iSeqId; string m_sBeginTime; string m_sEndTime; LARGE_INTEGER nBeginTime; LARGE_INTEGER nEndTime; //GetIndexBarsReq专用 int iCategory; }; #endif
// stdafx.h : 标准系统包含文件的包含文件, // 或是经常使用但不常更改的 // 特定于项目的包含文件 // #pragma once //#include "targetver.h" #include <stdio.h> #include <tchar.h> #include <winsock2.h> #include <windows.h> // TODO: 在此处引用程序需要的其他头文件
#ifndef _UTIL_HPP_ #define _UTIL_HPP_ #include "stdafx.h" #include <string> extern void log_packet(const char* data, size_t len); extern void test_packet_from_file(const std::string& filename ); extern const uchar * stock_code_search (const uchar * str, unsigned int len); extern bool stockcode_is_valid(const uchar * s); extern bool is_file_exist(const std::string& filename); std::string get_raw_string(std::string const& s); int getNowStr( std::string& sNow ); double getTimeDiff( const LARGE_INTEGER& a, const LARGE_INTEGER& b ); //===================================== int SetNonBlock( SOCKET iSock, unsigned long on ); int SetNoDelay( SOCKET iSock, char on ); int SetLinger( SOCKET iSock, struct linger stLinger ); #endif
#include "stdafx.h" #include "config.h" #include <iostream> #include <fstream> #include <string> #include <sstream> #include "response.h" #include "stock.h" #include <Windows.h> using namespace std; bool is_file_exist(const string& filename) { bool isOpen; ifstream ifs; ifs.open(filename.c_str()); isOpen = ifs.is_open(); ifs.close(); return isOpen; } bool stockcode_is_valid(const uchar * s) { bool valid = true; for(int i = 0; i < MarketInfo::StocksCodeLen; ++i) { if(s[i] < '0' || s[i] > '9') { valid = false; break; } } return valid; } const uchar * stock_code_search (const uchar * str, unsigned int len) { const uchar *cp = str; while (len -- > 0) { if(stockcode_is_valid(cp)) return cp; cp++; } return 0; } void log_packet(const char* data, size_t len) { const string path = "F:\\Develop\\stock\\data\\exc_log\\exc"; string filename; for(int i = 0; i < 1000; i++) { stringstream ss; ss << i << ".dat"; filename = path + ss.str(); if(!is_file_exist(filename)) { ofstream ofs(filename.c_str(), ios::out | ios::binary); ofs.write(data, len); break; } } } std::string get_raw_string(std::string const& s) { std::ostringstream out; out << '\"'; out << std::hex; for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { // AND 0xFF will remove the leading "ff" in the output, // So that we could get "\xab" instead of "\xffab" out << " " << (static_cast<short>(*it) & 0xff); } out << '\"'; ofstream outfile; outfile.open( "D:\\1.txt" ); outfile<<out.str() << endl; outfile.close(); return out.str(); } int getNowStr( std::string& sNow ) { SYSTEMTIME stNow; GetLocalTime( &stNow ); char sNowStr[32]; memset( sNowStr, 0, sizeof( sNowStr ) ); sprintf( sNowStr, "%4d-%02d-%02d %02d:%02d:%02d.%03d",stNow.wYear,stNow.wMonth,stNow.wDay, stNow.wHour,stNow.wMinute, stNow.wSecond,stNow.wMilliseconds ); sNow = sNowStr; return 0; } double getTimeDiff( const LARGE_INTEGER& nBeginTime, const LARGE_INTEGER& nEndTime ) { LARGE_INTEGER nFreq; QueryPerformanceFrequency( &nFreq ); // 获取时钟周期 //cout << "nFreq.QuadPart is:" << nFreq.QuadPart << endl; return (double)(nEndTime.QuadPart- nBeginTime.QuadPart)*1000.0/ nFreq.QuadPart; } //============================= int SetNonBlock( SOCKET iSock, unsigned long on ) { return ioctlsocket( iSock, FIONBIO, &on ); } int SetNoDelay( SOCKET iSock, char on ) { return setsockopt( iSock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(char)); } int SetLinger( SOCKET iSock, struct linger stLinger ) { return setsockopt( iSock, SOL_SOCKET, SO_LINGER, (char FAR *) &stLinger, sizeof(stLinger) ); }
#include "stdafx.h" #include "config.h" #include <string> #include <vector> #include <set> #include <map> #include <iostream> #include <sstream> #include "stockio.h" #include "util.hpp" #include "stock.h" using namespace std; // using namespace assign; const float MarketInfo::tax = 0.01f; // 1 % unsigned int MarketInfo::stocks_count[MarketInfo::MARKET_MAX]; StringSet MarketInfo::stocks_set[MarketInfo::MARKET_MAX]; StockTransact::DateTransact today_transact; StockTransact::TransactMap hist_transact; StockBid::BidMap instant_price_list; string StockBasicInfo::get_gbbq_file_name(uint tr_date) { const string stock_gbbq_file = "F:\\Develop\\stock\\data\\G"; stringstream ss; ss << stock_gbbq_file << tr_date << ".mat"; return ss.str(); } bool StockBasicInfo::is_gbbq_file_exist(uint tr_date) { return is_file_exist(get_gbbq_file_name(tr_date)); } void StockBasicInfo::clear_gbbq_info() { stock_gbbq_info.clear(); } bool StockBasicInfo::load_basic_info() { // 加载股票基本资料 // 基本信息 stock_base_info.clear(); BaseInfo bs; const string stock_data_path = "C:\\Program Files\\xyzq\\T0002\\"; string full_path = stock_data_path + "BASE.DBF"; fstream fs(full_path.c_str(), ios::in); // fstream ofs("d:\\temp\\t.txt", ios::out); if(!fs) return false; int record_off = 0x522; fs.seekg(record_off); char c; fs >> c; while(!fs.eof() && -1 != fs.tellg()) { fs >> bs; record_off += BaseInfo::record_len; stock_base_info.insert(make_pair(bs.stock_code, bs)); // ofs << bs.stock_code << endl; fs.seekg(record_off); fs >> c; } return true; } bool StockBasicInfo::load_block_info() { // 加载板块资料 stock_block_info.clear(); const string stock_data_path = "C:\\Program Files\\xyzq\\T0002\\"; string full_path = stock_data_path + "BLOCK.DAT"; fstream fs(full_path.c_str(), ios::in | ios::binary); if(!fs) return false; int p = 0; fs.seekg(0x182); while(!fs.eof() && -1 != (p =fs.tellg())) { char temp[10]; fs.read(&temp[0],9); if(0 == temp[0]) break; string name(temp); // block name unsigned short cnt = 0; fs.read((char*)&cnt, 2); fs.seekg(2, ios::cur); while(cnt -- > 0) { fs.read(&temp[0],7); if(0 == temp[0]) break; string member(temp, 6); stock_block_info[name].push_back(member); } fs.seekg(p + 0x0afd); } return true; } void StockBasicInfo::add_stock_gbbq(uint dt, const GBBQ& gbbq) { stock_gbbq_info[dt].push_back(gbbq); } bool StockTransact::Transact::operator == (const StockTransact::Transact& t) { return (minute == t.minute && price == t.price && vol == t.vol && bs == t.bs); } const int BaseInfo::record_len = 0x1e1; fstream& operator >> (fstream& fs, BaseInfo& bs) { char code[MarketInfo::StocksCodeLen]; fs.read(code, MarketInfo::StocksCodeLen); bs.stock_code = string(&code[0], MarketInfo::StocksCodeLen); fs >> bs.update_time; fs >> bs.ttl_amount; fs >> bs.state_own_amount; // 国家股 fs >> bs.init_amount; // 发起股本 fs >> bs.corp_amount; // 法人股本 fs >> bs.b_amount; // B 股本 fs >> bs.h_amount; // H 股本 fs >> bs.cir_amount; // 流通 股本 fs >> bs.empl_amount; // 职工 股本 fs >> bs.unknown1; // fs >> bs.ttl_asset; // 总资产 fs >> bs.varible_asset; // 流动 资产 fs >> bs.firm_asset; // 固定 资产 fs >> bs.invisible_asset; // 无形 资产 fs >> bs.long_term_invest; // 长期投资 fs >> bs.varible_debt; // 流动负债 fs >> bs.long_term_debt; // 长期负债 fs >> bs.accu_fund; // 公积金 fs >> bs.net_asset; // 净资产 fs >> bs.major_income; // 主营收入 fs >> bs.major_profit; // 主营利润 fs >> bs.unknown2; // fs >> bs.bussiness_income; // 营业收入 fs >> bs.invest_income; // 投资收入 fs >> bs.allowance; // 补贴收入 fs >> bs.non_bussiness_income; // 业外收入 fs >> bs.income_adjustment; // 收入调整 fs >> bs.ttl_profit; // 利润总额 fs >> bs.unknown3; // fs >> bs.net_profit; // 税后利润 fs >> bs.undist_profit; // 未分配利润 fs >> bs.per_net_assert2; // 每股净资产2 return fs; } extern void output_short_index_data(); string MarketInfo::get_first_stock() { // set the first stock for(short m = MarketInfo::MARKET_FIRST; m < MarketInfo::MARKET_MAX; m++) { StringSet::const_iterator iter = MarketInfo::stocks_set[m].begin(); if(iter != MarketInfo::stocks_set[m].end()) { return *iter; } } return ""; } string MarketInfo::find_next_stock(const string& stock_code) { bool first_in_market = false; for(short m = MarketInfo::get_market_type(stock_code); m < MarketInfo::MARKET_MAX; m++) { StringSet::const_iterator iter ; if(! first_in_market) { iter = MarketInfo::stocks_set[m].find(stock_code); if( iter != MarketInfo::stocks_set[m].end()) { ++iter; if(iter != MarketInfo::stocks_set[m].end()) { return *iter; } } first_in_market = true; } else { iter = MarketInfo::stocks_set[m].begin(); if(iter != MarketInfo::stocks_set[m].end()) { return *iter; } } } return ""; } void show_curr_bid(char const* first, char const* last ) { cout << "show_curr_bid called\r\n"; StockBid::BidMap::const_iterator i = instant_price_list.begin(); // has data if(i != instant_price_list.end()) { // print title here } while(i++ != instant_price_list.end()) { cout << i->first << endl; } }