2019-02-08 22:41:20 +08:00
|
|
|
|
/*
|
2015-01-07 01:26:14 +08:00
|
|
|
|
* Stock.h
|
|
|
|
|
*
|
|
|
|
|
* Created on: 2011-11-9
|
|
|
|
|
* Author: fasiondog
|
|
|
|
|
*/
|
|
|
|
|
|
2019-08-03 21:53:24 +08:00
|
|
|
|
#pragma once
|
2015-01-07 01:26:14 +08:00
|
|
|
|
#ifndef STOCK_H_
|
|
|
|
|
#define STOCK_H_
|
|
|
|
|
|
2020-11-11 00:07:56 +08:00
|
|
|
|
#include <shared_mutex>
|
2015-01-07 01:26:14 +08:00
|
|
|
|
#include "StockWeight.h"
|
|
|
|
|
#include "KQuery.h"
|
2019-02-08 22:41:20 +08:00
|
|
|
|
#include "TimeLineRecord.h"
|
2019-02-11 21:13:06 +08:00
|
|
|
|
#include "TransRecord.h"
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
namespace hku {
|
|
|
|
|
|
|
|
|
|
class HKU_API StockManager;
|
2021-01-24 20:47:38 +08:00
|
|
|
|
class KDataDriverConnect;
|
2021-01-22 00:39:37 +08:00
|
|
|
|
|
2021-01-24 20:47:38 +08:00
|
|
|
|
template <class DriverConnectT>
|
|
|
|
|
class DriverConnectPool;
|
2021-01-22 00:39:37 +08:00
|
|
|
|
|
2021-01-24 20:47:38 +08:00
|
|
|
|
typedef DriverConnectPool<KDataDriverConnect> KDataDriverConnectPool;
|
|
|
|
|
typedef shared_ptr<KDataDriverConnectPool> KDataDriverConnectPoolPtr;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
class HKU_API KData;
|
2019-04-07 22:55:47 +08:00
|
|
|
|
class HKU_API Parameter;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stock基类,Application中一般使用StockPtr进行操作
|
|
|
|
|
* @ingroup StockManage
|
|
|
|
|
*/
|
|
|
|
|
class HKU_API Stock {
|
|
|
|
|
friend class StockManager;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
static const string default_market;
|
|
|
|
|
static const string default_code;
|
|
|
|
|
static const string default_market_code;
|
|
|
|
|
static const string default_name;
|
2020-10-01 22:52:50 +08:00
|
|
|
|
static const uint32_t default_type;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
static const bool default_valid;
|
|
|
|
|
static const Datetime default_startDate;
|
|
|
|
|
static const Datetime default_lastDate;
|
|
|
|
|
static const price_t default_tick;
|
|
|
|
|
static const price_t default_tickValue;
|
|
|
|
|
static const price_t default_unit;
|
|
|
|
|
static const int default_precision;
|
|
|
|
|
static const size_t default_minTradeNumber;
|
|
|
|
|
static const size_t default_maxTradeNumber;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Stock();
|
|
|
|
|
|
|
|
|
|
Stock(const Stock&);
|
2022-02-27 09:29:26 +08:00
|
|
|
|
Stock(Stock&&);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
Stock(const string& market, const string& code, const string& name);
|
|
|
|
|
|
2020-10-01 22:52:50 +08:00
|
|
|
|
Stock(const string& market, const string& code, const string& name, uint32_t type, bool valid,
|
2015-01-07 01:26:14 +08:00
|
|
|
|
const Datetime& startDate, const Datetime& lastDate);
|
2020-10-01 22:52:50 +08:00
|
|
|
|
Stock(const string& market, const string& code, const string& name, uint32_t type, bool valid,
|
|
|
|
|
const Datetime& startDate, const Datetime& lastDate, price_t tick, price_t tickValue,
|
|
|
|
|
int precision, size_t minTradeNumber, size_t maxTradeNumber);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
virtual ~Stock();
|
|
|
|
|
Stock& operator=(const Stock&);
|
2022-02-27 09:29:26 +08:00
|
|
|
|
Stock& operator=(Stock&&);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
bool operator==(const Stock&) const;
|
|
|
|
|
bool operator!=(const Stock&) const;
|
|
|
|
|
|
2021-01-29 00:18:01 +08:00
|
|
|
|
/**
|
|
|
|
|
* 获取内部id,一般用于作为map的键值使用,该id实际为m_data的内存地址
|
|
|
|
|
* @note 非数据库中的stockid
|
|
|
|
|
*/
|
2020-10-01 22:52:50 +08:00
|
|
|
|
uint64_t id() const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取所属市场简称,市场简称是市场的唯一标识 */
|
|
|
|
|
const string& market() const;
|
|
|
|
|
|
|
|
|
|
/** 获取证券代码 */
|
|
|
|
|
const string& code() const;
|
|
|
|
|
|
|
|
|
|
/** 市场简称+证券代码,如: sh000001 */
|
|
|
|
|
const string& market_code() const;
|
|
|
|
|
|
|
|
|
|
/** 获取证券名称 */
|
|
|
|
|
const string& name() const;
|
|
|
|
|
|
|
|
|
|
/** 获取证券类型 */
|
2020-10-01 22:52:50 +08:00
|
|
|
|
uint32_t type() const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 该证券当前是否有效 */
|
|
|
|
|
bool valid() const;
|
|
|
|
|
|
|
|
|
|
/** 获取证券起始日期 */
|
|
|
|
|
Datetime startDatetime() const;
|
|
|
|
|
|
|
|
|
|
/** 获取证券最后日期 */
|
|
|
|
|
Datetime lastDatetime() const;
|
|
|
|
|
|
|
|
|
|
/** 获取最小跳动量 */
|
|
|
|
|
price_t tick() const;
|
|
|
|
|
|
|
|
|
|
/** 最小跳动量价值 */
|
|
|
|
|
price_t tickValue() const;
|
|
|
|
|
|
|
|
|
|
/** 每单位价值 = tickValue / tick */
|
|
|
|
|
price_t unit() const;
|
|
|
|
|
|
|
|
|
|
/** 获取价格精度 */
|
|
|
|
|
int precision() const;
|
|
|
|
|
|
|
|
|
|
/** 获取最小交易数量,同minTradeNumber */
|
2022-02-20 01:42:11 +08:00
|
|
|
|
double atom() const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取最小交易数量 */
|
2022-02-20 01:42:11 +08:00
|
|
|
|
double minTradeNumber() const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取最大交易量 */
|
2022-02-20 01:42:11 +08:00
|
|
|
|
double maxTradeNumber() const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取指定时间段[start,end)内的权息信息
|
|
|
|
|
* @param start 起始日期
|
|
|
|
|
* @param end 结束日期
|
|
|
|
|
* @return 满足要求的权息信息列表指针
|
|
|
|
|
*/
|
2020-10-29 00:03:25 +08:00
|
|
|
|
StockWeightList getWeight(const Datetime& start = Datetime::min(),
|
|
|
|
|
const Datetime& end = Null<Datetime>()) const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取不同类型K线数据量 */
|
|
|
|
|
size_t getCount(KQuery::KType dataType = KQuery::DAY) const;
|
|
|
|
|
|
|
|
|
|
/** 获取指定日期时刻的市值,即小于等于指定日期的最后一条记录的收盘价 */
|
|
|
|
|
price_t getMarketValue(const Datetime&, KQuery::KType) const;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据KQuery指定的条件,获取对应的K线位置范围
|
|
|
|
|
* @param query [in] 指定的查询条件
|
|
|
|
|
* @param out_start [out] 对应的K线起始范围
|
|
|
|
|
* @param out_end [out] 对应的K线结束范围,不包含自身
|
|
|
|
|
* @return true 成功 | false 失败
|
|
|
|
|
*/
|
2019-08-03 15:14:39 +08:00
|
|
|
|
bool getIndexRange(const KQuery& query, size_t& out_start, size_t& out_end) const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取指定索引的K线数据记录,未作越界检查 */
|
2024-01-28 23:38:03 +08:00
|
|
|
|
KRecord getKRecord(size_t pos, const KQuery::KType& dataType = KQuery::DAY) const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 根据数据类型(日线/周线等),获取指定日期的KRecord */
|
2024-01-28 23:38:03 +08:00
|
|
|
|
KRecord getKRecord(const Datetime&, const KQuery::KType& ktype = KQuery::DAY) const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** 获取K线数据 */
|
|
|
|
|
KData getKData(const KQuery&) const;
|
|
|
|
|
|
2020-10-03 00:02:03 +08:00
|
|
|
|
/**
|
2020-10-03 23:58:04 +08:00
|
|
|
|
* 根据查询条件获取 KRecordList,不建议在客户端直接使用
|
2020-10-05 00:07:29 +08:00
|
|
|
|
* @note 该方法不支持复权
|
2020-10-03 00:02:03 +08:00
|
|
|
|
* @param query 查询条件
|
|
|
|
|
*/
|
|
|
|
|
KRecordList getKRecordList(const KQuery& query) const;
|
|
|
|
|
|
2016-04-25 01:39:07 +08:00
|
|
|
|
/** 获取日期列表 */
|
|
|
|
|
DatetimeList getDatetimeList(const KQuery& query) const;
|
|
|
|
|
|
2019-02-08 22:41:20 +08:00
|
|
|
|
/** 获取分时线 */
|
2019-02-11 16:33:55 +08:00
|
|
|
|
TimeLineList getTimeLineList(const KQuery& query) const;
|
2019-02-08 22:41:20 +08:00
|
|
|
|
|
2019-02-11 21:13:06 +08:00
|
|
|
|
/** 获取历史分笔数据 */
|
|
|
|
|
TransList getTransList(const KQuery& query) const;
|
|
|
|
|
|
2019-04-07 22:55:47 +08:00
|
|
|
|
/**
|
|
|
|
|
* 获取当前财务信息
|
|
|
|
|
*/
|
|
|
|
|
Parameter getFinanceInfo() const;
|
2019-11-10 19:45:57 +08:00
|
|
|
|
|
|
|
|
|
/**
|
2019-04-06 02:40:53 +08:00
|
|
|
|
* 获取历史财务信息
|
|
|
|
|
* @param date 指定日期必须是0331、0630、0930、1231,如 Datetime(201109300000)
|
|
|
|
|
*/
|
|
|
|
|
PriceList getHistoryFinanceInfo(const Datetime& date) const;
|
|
|
|
|
|
2020-10-29 00:03:25 +08:00
|
|
|
|
/** 设置权息信息, 仅供初始化时调用 */
|
2015-01-07 01:26:14 +08:00
|
|
|
|
void setWeightList(const StockWeightList&);
|
|
|
|
|
|
2021-01-06 00:06:58 +08:00
|
|
|
|
/**
|
|
|
|
|
* 判断是否在交易时间段内,忽略日期仅判断时分秒
|
|
|
|
|
* @param time 时间
|
|
|
|
|
*/
|
|
|
|
|
bool isTransactionTime(Datetime time);
|
|
|
|
|
|
2021-02-07 00:56:04 +08:00
|
|
|
|
/** 设置K线数据驱动 */
|
2021-01-24 20:47:38 +08:00
|
|
|
|
void setKDataDriver(const KDataDriverConnectPoolPtr& kdataDriver);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
2021-02-07 00:56:04 +08:00
|
|
|
|
/** 获取K线驱动*/
|
|
|
|
|
KDataDriverConnectPoolPtr getKDataDirver() const;
|
|
|
|
|
|
2015-01-07 01:26:14 +08:00
|
|
|
|
/**
|
|
|
|
|
* 将K线数据做自身缓存
|
2019-02-08 22:41:20 +08:00
|
|
|
|
* @note 一般不主动调用,谨慎
|
2015-01-07 01:26:14 +08:00
|
|
|
|
*/
|
|
|
|
|
void loadKDataToBuffer(KQuery::KType);
|
|
|
|
|
|
|
|
|
|
/** 释放对应的K线缓存 */
|
|
|
|
|
void releaseKDataBuffer(KQuery::KType);
|
|
|
|
|
|
|
|
|
|
/** 指定类型的K线数据是否被缓存 */
|
|
|
|
|
bool isBuffer(KQuery::KType) const;
|
|
|
|
|
|
|
|
|
|
/** 是否为Null */
|
|
|
|
|
bool isNull() const;
|
|
|
|
|
|
2022-06-30 00:51:09 +08:00
|
|
|
|
/** (临时函数)只用于更新缓存中的K线数据 **/
|
2020-12-19 23:57:24 +08:00
|
|
|
|
void realtimeUpdate(KRecord, KQuery::KType ktype = KQuery::DAY);
|
2016-04-03 00:08:31 +08:00
|
|
|
|
|
|
|
|
|
/** 仅用于python的__str__ */
|
|
|
|
|
string toString() const;
|
|
|
|
|
|
2015-01-07 01:26:14 +08:00
|
|
|
|
private:
|
|
|
|
|
bool _getIndexRangeByIndex(const KQuery&, size_t& out_start, size_t& out_end) const;
|
2020-11-11 23:58:08 +08:00
|
|
|
|
|
2020-11-12 23:54:01 +08:00
|
|
|
|
// 以下函数属于基础操作添加了读锁
|
2020-11-11 23:58:08 +08:00
|
|
|
|
size_t _getCountFromBuffer(KQuery::KType ktype) const;
|
2024-01-28 23:38:03 +08:00
|
|
|
|
KRecord _getKRecordFromBuffer(size_t pos, const KQuery::KType& ktype) const;
|
2020-11-11 23:58:08 +08:00
|
|
|
|
KRecordList _getKRecordListFromBuffer(size_t start_ix, size_t end_ix,
|
|
|
|
|
KQuery::KType ktype) const;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
bool _getIndexRangeByDateFromBuffer(const KQuery&, size_t&, size_t&) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
struct HKU_API Data;
|
|
|
|
|
shared_ptr<Data> m_data;
|
2021-01-24 20:47:38 +08:00
|
|
|
|
KDataDriverConnectPoolPtr m_kdataDriver;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct HKU_API Stock::Data {
|
2023-10-28 17:42:43 +08:00
|
|
|
|
string m_market; // 所属的市场简称
|
|
|
|
|
string m_code; // 证券代码
|
|
|
|
|
string m_market_code; // 市场简称证券代码
|
|
|
|
|
string m_name; // 证券名称
|
|
|
|
|
uint32_t m_type; // 证券类型
|
|
|
|
|
bool m_valid; // 当前证券是否有效
|
|
|
|
|
Datetime m_startDate; // 证券起始日期
|
|
|
|
|
Datetime m_lastDate; // 证券最后日期
|
2023-07-28 23:50:26 +08:00
|
|
|
|
|
|
|
|
|
StockWeightList m_weightList; // 权息信息列表
|
2021-01-26 00:21:34 +08:00
|
|
|
|
std::mutex m_weight_mutex;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
price_t m_tick;
|
|
|
|
|
price_t m_tickValue;
|
|
|
|
|
price_t m_unit;
|
2019-11-10 19:45:57 +08:00
|
|
|
|
int m_precision;
|
2022-02-20 01:42:11 +08:00
|
|
|
|
double m_minTradeNumber;
|
|
|
|
|
double m_maxTradeNumber;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
2020-10-05 18:04:53 +08:00
|
|
|
|
unordered_map<string, KRecordList*> pKData;
|
2020-11-11 00:07:56 +08:00
|
|
|
|
unordered_map<string, std::shared_mutex*> pMutex;
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
Data();
|
2020-10-01 22:52:50 +08:00
|
|
|
|
Data(const string& market, const string& code, const string& name, uint32_t type, bool valid,
|
|
|
|
|
const Datetime& startDate, const Datetime& lastDate, price_t tick, price_t tickValue,
|
2022-02-20 01:42:11 +08:00
|
|
|
|
int precision, double minTradeNumber, double maxTradeNumber);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
virtual ~Data();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 输出Stock信息,如:Stock(market, code, name, type, valid, startDatetime, lastDatetime)
|
|
|
|
|
* @ingroup StockManage
|
|
|
|
|
*/
|
2019-11-10 19:45:57 +08:00
|
|
|
|
HKU_API std::ostream& operator<<(std::ostream& os, const Stock& stock);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
|
|
|
|
/** @ingroup StockManage */
|
|
|
|
|
typedef vector<Stock> StockList;
|
|
|
|
|
|
2019-03-03 20:47:28 +08:00
|
|
|
|
/**
|
|
|
|
|
* 获取Stock,目的是封装StockManager,客户端不直接使用StockManager对象
|
|
|
|
|
* @param querystr 格式:“市场简称证券代码”,如"sh000001"
|
|
|
|
|
* @return 对应的证券实例,如果实例不存在,则Null<Stock>(),不抛出异常
|
|
|
|
|
* @ingroup StockManage
|
|
|
|
|
*/
|
|
|
|
|
Stock HKU_API getStock(const string& querystr);
|
|
|
|
|
|
2015-01-07 01:26:14 +08:00
|
|
|
|
/* 用于将Stock实例作为map的key,一般建议使用stock.id做键值,
|
|
|
|
|
* 否则map还要利用拷贝构造函数,创建新对象,效率低 */
|
2019-11-10 19:45:57 +08:00
|
|
|
|
bool operator<(const Stock& s1, const Stock& s2);
|
|
|
|
|
inline bool operator<(const Stock& s1, const Stock& s2) {
|
2015-01-07 01:26:14 +08:00
|
|
|
|
return s1.id() < s2.id();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 22:52:50 +08:00
|
|
|
|
inline uint64_t Stock::id() const {
|
|
|
|
|
return isNull() ? 0 : (int64_t)m_data.get();
|
2015-01-07 01:26:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-10-28 17:42:43 +08:00
|
|
|
|
inline bool Stock::operator!=(const Stock& stock) const {
|
|
|
|
|
return !(*this == stock);
|
2015-01-07 01:26:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-10 19:45:57 +08:00
|
|
|
|
} // namespace hku
|
2015-01-07 01:26:14 +08:00
|
|
|
|
|
2021-02-22 23:52:16 +08:00
|
|
|
|
namespace std {
|
|
|
|
|
template <>
|
2021-03-26 01:22:40 +08:00
|
|
|
|
class hash<hku::Stock> {
|
|
|
|
|
public:
|
|
|
|
|
size_t operator()(hku::Stock const& stk) const noexcept {
|
2021-02-22 23:52:16 +08:00
|
|
|
|
return stk.id(); // or use boost::hash_combine
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
} // namespace std
|
|
|
|
|
|
2023-07-28 23:50:26 +08:00
|
|
|
|
#if FMT_VERSION >= 90000
|
|
|
|
|
template <>
|
|
|
|
|
struct fmt::formatter<hku::Stock> : ostream_formatter {};
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-01-07 01:26:14 +08:00
|
|
|
|
#endif /* STOCK_H_ */
|