hikyuu2/hikyuu_cpp/hikyuu/Stock.cpp

673 lines
19 KiB
C++
Raw Normal View History

2016-04-11 01:27:04 +08:00
/*
2015-01-07 01:26:14 +08:00
* Stock.cpp
*
* Created on: 2011-11-9
* Author: fasiondog
*/
#include "GlobalInitializer.h"
2015-01-07 01:26:14 +08:00
#include "StockManager.h"
#include "data_driver/KDataDriver.h"
2019-04-06 02:40:53 +08:00
#include "data_driver/HistoryFinanceReader.h"
2016-04-03 00:08:31 +08:00
#include "utilities/util.h"
2019-02-08 22:41:20 +08:00
#include "KData.h"
2015-01-07 01:26:14 +08:00
namespace hku {
const string Stock::default_market;
2019-03-28 02:11:13 +08:00
const string Stock::default_code;
2015-01-07 01:26:14 +08:00
const string Stock::default_market_code;
const string Stock::default_name;
const uint32_t Stock::default_type = Null<uint32_t>();
2015-01-07 01:26:14 +08:00
const bool Stock::default_valid = false;
2019-11-10 03:27:57 +08:00
const Datetime Stock::default_startDate; // = Null<Datetime>();
const Datetime Stock::default_lastDate; // = Null<Datetime>();
2015-01-07 01:26:14 +08:00
const price_t Stock::default_tick = 0.01;
const price_t Stock::default_tickValue = 0.01;
const price_t Stock::default_unit = 1.0;
const int Stock::default_precision = 2;
const size_t Stock::default_minTradeNumber = 100;
const size_t Stock::default_maxTradeNumber = 1000000;
2019-11-10 03:27:57 +08:00
HKU_API std::ostream& operator<<(std::ostream& os, const Stock& stock) {
2015-01-07 01:26:14 +08:00
string strip(", ");
2019-11-10 19:45:57 +08:00
const StockManager& sm = StockManager::instance();
2015-01-07 01:26:14 +08:00
StockTypeInfo typeInfo(sm.getStockTypeInfo(stock.type()));
os << "Stock(" << stock.market() << strip << stock.code() << strip << stock.name() << strip
<< typeInfo.description() << strip << stock.valid() << strip << stock.startDatetime()
<< strip << stock.lastDatetime() << ")";
2015-01-07 01:26:14 +08:00
return os;
}
2016-04-03 00:08:31 +08:00
string Stock::toString() const {
std::stringstream os;
string strip(", ");
2019-11-10 19:45:57 +08:00
const StockManager& sm = StockManager::instance();
2016-04-03 00:08:31 +08:00
StockTypeInfo typeInfo(sm.getStockTypeInfo(type()));
os << "Stock(" << market() << strip << code() << strip << name() << strip
<< typeInfo.description() << strip << valid() << strip << startDatetime() << strip
<< lastDatetime() << ")";
2016-04-03 00:08:31 +08:00
return os.str();
}
2015-01-07 01:26:14 +08:00
Stock::Data::Data()
: m_market(default_market),
m_code(default_code),
m_name(default_name),
m_type(default_type),
m_valid(default_valid),
m_startDate(default_startDate),
m_lastDate(default_lastDate),
m_tick(default_tick),
m_tickValue(default_tickValue),
m_unit(default_unit),
m_precision(default_precision),
m_minTradeNumber(default_minTradeNumber),
2020-10-05 18:04:53 +08:00
m_maxTradeNumber(default_maxTradeNumber) {}
2015-01-07 01:26:14 +08:00
Stock::Data::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, int precision, size_t minTradeNumber, size_t maxTradeNumber)
2015-01-07 01:26:14 +08:00
: m_market(market),
m_code(code),
m_name(name),
m_type(type),
m_valid(valid),
m_startDate(startDate),
m_lastDate(lastDate),
m_tick(tick),
m_tickValue(tickValue),
m_precision(precision),
m_minTradeNumber(minTradeNumber),
m_maxTradeNumber(maxTradeNumber) {
if (0.0 == m_tick) {
2019-06-16 19:06:06 +08:00
HKU_WARN("tick should not be zero!");
2015-01-07 01:26:14 +08:00
m_unit = 1.0;
} else {
m_unit = m_tickValue / m_tick;
}
to_upper(m_market);
2015-01-07 01:26:14 +08:00
m_market_code = m_market + m_code;
}
Stock::Data::~Data() {
2020-10-05 18:04:53 +08:00
for (auto iter = pKData.begin(); iter != pKData.end(); ++iter) {
if (iter->second) {
delete iter->second;
}
}
2015-01-07 01:26:14 +08:00
}
Stock::Stock() {}
2015-01-07 01:26:14 +08:00
2019-11-10 03:27:57 +08:00
Stock::~Stock() {}
2015-01-07 01:26:14 +08:00
2019-11-10 19:45:57 +08:00
Stock::Stock(const Stock& x) : m_data(x.m_data), m_kdataDriver(x.m_kdataDriver) {}
2015-01-07 01:26:14 +08:00
Stock& Stock::operator=(const Stock& x) {
2019-11-10 03:27:57 +08:00
if (this == &x)
2015-01-07 01:26:14 +08:00
return *this;
2019-11-10 19:45:57 +08:00
m_data = x.m_data;
m_kdataDriver = x.m_kdataDriver;
2015-01-07 01:26:14 +08:00
return *this;
}
2019-11-10 03:27:57 +08:00
Stock::Stock(const string& market, const string& code, const string& name) {
m_data =
shared_ptr<Data>(new Data(market, code, name, default_type, default_valid, default_startDate,
default_lastDate, default_tick, default_tickValue,
default_precision, default_minTradeNumber, default_maxTradeNumber));
2015-01-07 01:26:14 +08:00
}
Stock::Stock(const string& market, const string& code, const string& name, uint32_t type,
bool valid, const Datetime& startDate, const Datetime& lastDate) {
m_data = shared_ptr<Data>(new Data(market, code, name, type, valid, startDate, lastDate,
default_tick, default_tickValue, default_precision,
default_minTradeNumber, default_maxTradeNumber));
2015-01-07 01:26:14 +08:00
}
Stock::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)
: m_data(make_shared<Data>(market, code, name, type, valid, startDate, lastDate, tick, tickValue,
precision, minTradeNumber, maxTradeNumber)) {}
2015-01-07 01:26:14 +08:00
bool Stock::operator!=(const Stock& stock) const {
if (this == &stock)
return false;
if (m_data == stock.m_data)
return false;
if (!m_data || !stock.m_data)
return true;
2019-11-10 03:27:57 +08:00
if (m_data->m_code != stock.code() || m_data->m_market != stock.market())
2015-01-07 01:26:14 +08:00
return true;
return false;
}
const string& Stock::market() const {
return m_data ? m_data->m_market : default_market;
}
const string& Stock::code() const {
return m_data ? m_data->m_code : default_code;
}
const string& Stock::market_code() const {
return m_data ? m_data->m_market_code : default_market_code;
}
const string& Stock::name() const {
return m_data ? m_data->m_name : default_name;
}
uint32_t Stock::type() const {
2015-01-07 01:26:14 +08:00
return m_data ? m_data->m_type : default_type;
}
bool Stock::valid() const {
return m_data ? m_data->m_valid : default_valid;
}
Datetime Stock::startDatetime() const {
return m_data ? m_data->m_startDate : default_startDate;
}
Datetime Stock::lastDatetime() const {
return m_data ? m_data->m_lastDate : default_lastDate;
}
price_t Stock::tick() const {
return m_data ? m_data->m_tick : default_tick;
}
price_t Stock::tickValue() const {
return m_data ? m_data->m_tickValue : default_tickValue;
}
price_t Stock::unit() const {
return m_data ? m_data->m_unit : default_unit;
}
int Stock::precision() const {
return m_data ? m_data->m_precision : default_precision;
}
size_t Stock::atom() const {
return m_data ? m_data->m_minTradeNumber : default_minTradeNumber;
}
size_t Stock::minTradeNumber() const {
return m_data ? m_data->m_minTradeNumber : default_minTradeNumber;
}
size_t Stock::maxTradeNumber() const {
return m_data ? m_data->m_maxTradeNumber : default_maxTradeNumber;
}
void Stock::setKDataDriver(const KDataDriverPtr& kdataDriver) {
HKU_CHECK(kdataDriver, "kdataDriver is nullptr!");
m_kdataDriver = kdataDriver;
2020-10-06 17:56:10 +08:00
if (m_data) {
for (auto iter = m_data->pKData.begin(); iter != m_data->pKData.end(); ++iter) {
delete iter->second;
}
m_data->pKData.clear();
}
2015-01-07 01:26:14 +08:00
}
void Stock::setWeightList(const StockWeightList& weightList) {
if (m_data)
m_data->m_weightList = weightList;
}
KDataDriverPtr Stock::getKDataDriver() const {
return m_kdataDriver;
}
bool Stock::isBuffer(KQuery::KType ktype) const {
if (!m_data)
return false;
2020-06-10 00:17:24 +08:00
string nktype(ktype);
2020-10-05 18:04:53 +08:00
to_upper(nktype);
2020-10-08 02:26:02 +08:00
return m_data->pKData.find(nktype) != m_data->pKData.end();
2015-01-07 01:26:14 +08:00
}
bool Stock::isNull() const {
2020-10-05 18:04:53 +08:00
return !m_data || !m_kdataDriver;
2015-01-07 01:26:14 +08:00
}
2020-06-10 00:17:24 +08:00
void Stock::releaseKDataBuffer(KQuery::KType inkType) {
2020-10-05 18:04:53 +08:00
if (m_data) {
string kType(inkType);
to_upper(kType);
auto iter = m_data->pKData.find(kType);
if (iter != m_data->pKData.end()) {
delete iter->second;
m_data->pKData.erase(kType);
}
}
2015-01-07 01:26:14 +08:00
}
2020-06-10 00:17:24 +08:00
void Stock::loadKDataToBuffer(KQuery::KType inkType) {
2020-10-05 18:04:53 +08:00
if (m_data) {
string kType(inkType);
to_upper(kType);
2020-06-10 00:17:24 +08:00
2020-10-05 18:04:53 +08:00
releaseKDataBuffer(kType);
m_data->pKData[kType] = new KRecordList;
if (m_kdataDriver) {
*(m_data->pKData[kType]) = m_kdataDriver->getKRecordList(
m_data->m_market, m_data->m_code, KQuery(0, Null<int64_t>(), kType));
}
}
2015-01-07 01:26:14 +08:00
}
2019-11-10 03:27:57 +08:00
StockWeightList Stock::getWeight(const Datetime& start, const Datetime& end) const {
2015-01-07 01:26:14 +08:00
StockWeightList result;
if (!m_data || start >= end)
return result;
StockWeightList::const_iterator start_iter, end_iter;
start_iter = lower_bound(m_data->m_weightList.begin(), m_data->m_weightList.end(), start,
std::less<StockWeight>());
2019-11-10 03:27:57 +08:00
if (start_iter == m_data->m_weightList.end()) {
2015-01-07 01:26:14 +08:00
return result;
}
end_iter = lower_bound(start_iter, (StockWeightList::const_iterator)m_data->m_weightList.end(),
end, std::less<StockWeight>());
2019-11-10 03:27:57 +08:00
for (; start_iter != end_iter; ++start_iter) {
2015-01-07 01:26:14 +08:00
result.push_back(*start_iter);
}
return result;
}
KData Stock::getKData(const KQuery& query) const {
return KData(*this, query);
}
size_t Stock::getCount(KQuery::KType kType) const {
if (!m_data)
2015-01-07 01:26:14 +08:00
return 0;
2020-06-10 00:17:24 +08:00
string nktype(kType);
to_upper(nktype);
if (m_data->pKData.find(nktype) != m_data->pKData.end()) {
return m_data->pKData[nktype]->size();
}
2015-01-07 01:26:14 +08:00
2020-06-10 00:17:24 +08:00
return m_kdataDriver ? m_kdataDriver->getCount(market(), code(), nktype) : 0;
2015-01-07 01:26:14 +08:00
}
2020-06-10 00:17:24 +08:00
price_t Stock::getMarketValue(const Datetime& datetime, KQuery::KType inktype) const {
2020-10-08 15:46:41 +08:00
if (isNull())
2015-01-07 01:26:14 +08:00
return 0.0;
2020-10-08 15:46:41 +08:00
if (!valid() && datetime > lastDatetime())
return 0.0;
2015-01-07 01:26:14 +08:00
2020-06-10 00:17:24 +08:00
string ktype(inktype);
to_upper(ktype);
2020-10-08 15:46:41 +08:00
// 如果为内存缓存或者数据驱动为索引优先,则按索引方式获取
if (m_data->pKData.find(ktype) != m_data->pKData.end() || m_kdataDriver->isIndexFirst()) {
KQuery query = KQueryByDate(datetime, Null<Datetime>(), ktype);
2020-10-08 02:26:02 +08:00
size_t out_start, out_end;
if (getIndexRange(query, out_start, out_end)) {
//找到的是>=datetime的记录
KRecord k = getKRecord(out_start, ktype);
if (k.datetime == datetime) {
2020-10-08 15:46:41 +08:00
return k.closePrice;
}
if (out_start != 0) {
k = getKRecord(out_start - 1, ktype);
return k.closePrice;
2015-01-07 01:26:14 +08:00
}
}
2020-10-08 15:46:41 +08:00
2015-01-07 01:26:14 +08:00
} else {
2020-10-08 15:46:41 +08:00
// 未在缓存中,且日期优先的情况下
// 先尝试获取等于该日期的K线数据
// 如未找到,则获取小于该日期的最后一条记录
KQuery query = KQueryByDate(datetime, datetime + Minutes(1), ktype);
2020-10-08 02:26:02 +08:00
auto k_list = getKRecordList(query);
2020-10-08 15:46:41 +08:00
if (k_list.size() > 0 && k_list[0].datetime == datetime) {
return k_list[0].closePrice;
}
query = KQueryByDate(startDatetime(), datetime, ktype);
k_list = getKRecordList(query);
2020-10-08 02:26:02 +08:00
if (k_list.size() > 0) {
2020-10-08 15:46:41 +08:00
return k_list[k_list.size() - 1].closePrice;
2020-10-08 02:26:02 +08:00
}
}
2020-10-08 15:46:41 +08:00
//没有找到,则取最后一条记录
price_t price = 0.0;
size_t total = getCount(ktype);
if (total > 0) {
price = getKRecord(total - 1, ktype).closePrice;
2015-01-07 01:26:14 +08:00
}
return price;
}
2019-11-10 03:27:57 +08:00
bool Stock::getIndexRange(const KQuery& query, size_t& out_start, size_t& out_end) const {
2015-01-07 01:26:14 +08:00
out_start = 0;
out_end = 0;
if (!m_data || !m_kdataDriver)
return false;
if (KQuery::INDEX == query.queryType())
return _getIndexRangeByIndex(query, out_start, out_end);
2020-10-08 15:46:41 +08:00
if ((KQuery::DATE != query.queryType()) || query.startDatetime() >= query.endDatetime())
2015-01-07 01:26:14 +08:00
return false;
if (isBuffer(query.kType())) {
2015-01-07 01:26:14 +08:00
return _getIndexRangeByDateFromBuffer(query, out_start, out_end);
}
if (!m_kdataDriver->getIndexRangeByDate(m_data->m_market, m_data->m_code, query, out_start,
out_end)) {
2015-01-07 01:26:14 +08:00
out_start = 0;
out_end = 0;
return false;
}
return true;
}
2019-11-10 03:27:57 +08:00
bool Stock::_getIndexRangeByIndex(const KQuery& query, size_t& out_start, size_t& out_end) const {
2015-01-07 01:26:14 +08:00
assert(query.queryType() == KQuery::INDEX);
out_start = 0;
out_end = 0;
size_t total = getCount(query.kType());
if (0 == total) {
return false;
}
int64_t startix, endix;
2015-01-07 01:26:14 +08:00
startix = query.start();
2019-11-10 03:27:57 +08:00
if (startix < 0) {
2015-01-07 01:26:14 +08:00
startix += total;
2019-11-10 03:27:57 +08:00
if (startix < 0)
2015-01-07 01:26:14 +08:00
startix = 0;
}
endix = query.end();
2019-11-10 03:27:57 +08:00
if (endix < 0) {
2015-01-07 01:26:14 +08:00
endix += total;
2019-11-10 03:27:57 +08:00
if (endix < 0)
2015-01-07 01:26:14 +08:00
endix = 0;
}
2017-05-15 01:38:18 +08:00
size_t null_size_t = Null<size_t>();
size_t startpos = 0;
size_t endpos = null_size_t;
try {
startpos = boost::numeric_cast<size_t>(startix);
2019-11-10 03:27:57 +08:00
} catch (...) {
2017-05-15 01:38:18 +08:00
startpos = null_size_t;
}
try {
endpos = boost::numeric_cast<size_t>(endix);
} catch (...) {
endpos = null_size_t;
}
2015-01-07 01:26:14 +08:00
2019-11-10 03:27:57 +08:00
if (endpos > total) {
2015-01-07 01:26:14 +08:00
endpos = total;
}
2019-11-10 03:27:57 +08:00
if (startpos >= endpos) {
2015-01-07 01:26:14 +08:00
return false;
}
out_start = startpos;
out_end = endpos;
return true;
}
bool Stock::_getIndexRangeByDateFromBuffer(const KQuery& query, size_t& out_start,
size_t& out_end) const {
2015-01-07 01:26:14 +08:00
out_start = 0;
out_end = 0;
//总数为0视为失败
size_t total = getCount(query.kType());
2019-11-10 03:27:57 +08:00
if (0 == total) {
2015-01-07 01:26:14 +08:00
return false;
}
2019-11-10 19:45:57 +08:00
const KRecordList& kdata = *(m_data->pKData[query.kType()]);
2015-01-07 01:26:14 +08:00
size_t mid, low = 0, high = total - 1;
size_t startpos, endpos;
2019-11-10 03:27:57 +08:00
while (low <= high) {
if (query.startDatetime() > kdata[high].datetime) {
2015-01-07 01:26:14 +08:00
mid = high + 1;
break;
}
2019-11-10 03:27:57 +08:00
if (kdata[low].datetime >= query.startDatetime()) {
2015-01-07 01:26:14 +08:00
mid = low;
break;
}
mid = (low + high) / 2;
2019-11-10 03:27:57 +08:00
if (query.startDatetime() > kdata[mid].datetime) {
2015-01-07 01:26:14 +08:00
low = mid + 1;
} else {
high = mid - 1;
}
}
2019-11-10 03:27:57 +08:00
if (mid >= total) {
2015-01-07 01:26:14 +08:00
return false;
}
startpos = mid;
low = mid;
high = total - 1;
2019-11-10 03:27:57 +08:00
while (low <= high) {
if (query.endDatetime() > kdata[high].datetime) {
2015-01-07 01:26:14 +08:00
mid = high + 1;
break;
}
2019-11-10 03:27:57 +08:00
if (kdata[low].datetime >= query.endDatetime()) {
2015-01-07 01:26:14 +08:00
mid = low;
break;
}
mid = (low + high) / 2;
2019-11-10 03:27:57 +08:00
if (query.endDatetime() > kdata[mid].datetime) {
2015-01-07 01:26:14 +08:00
low = mid + 1;
} else {
high = mid - 1;
}
}
endpos = (mid >= total) ? total : mid;
2019-11-10 03:27:57 +08:00
if (startpos >= endpos) {
2015-01-07 01:26:14 +08:00
return false;
}
out_start = startpos;
out_end = endpos;
return true;
}
2020-10-09 01:02:52 +08:00
KRecord Stock::getKRecord(size_t pos, KQuery::KType kType) const {
if (!m_data)
2020-10-08 23:56:43 +08:00
return Null<KRecord>();
2020-06-10 00:17:24 +08:00
if (m_data->pKData.find(kType) != m_data->pKData.end())
2015-01-07 01:26:14 +08:00
return m_data->pKData[kType]->at(pos);
2020-10-08 23:56:43 +08:00
if (!m_kdataDriver || pos >= size_t(Null<int64_t>()))
return Null<KRecord>();
auto klist = m_kdataDriver->getKRecordList(market(), code(), KQuery(pos, pos + 1, kType));
return klist.size() > 0 ? klist[0] : Null<KRecord>();
2015-01-07 01:26:14 +08:00
}
2020-10-11 01:37:19 +08:00
KRecord Stock::getKRecord(const Datetime& datetime, KQuery::KType ktype) const {
2020-10-10 01:33:43 +08:00
KRecord result;
2020-10-08 15:46:41 +08:00
if (isNull())
2020-10-10 01:33:43 +08:00
return result;
2020-10-08 15:46:41 +08:00
2020-10-11 01:37:19 +08:00
// string ktype(inktype);
// to_upper(ktype);
2020-10-08 15:46:41 +08:00
2020-10-11 01:37:19 +08:00
KQuery query = KQueryByDate(datetime, datetime + Minutes(1), ktype);
2020-10-08 15:46:41 +08:00
size_t startix = 0, endix = 0;
if (m_data->pKData.find(ktype) != m_data->pKData.end() || m_kdataDriver->isIndexFirst()) {
2020-10-11 01:37:19 +08:00
return getIndexRange(query, startix, endix) ? getKRecord(startix, ktype) : Null<KRecord>();
2020-10-08 15:46:41 +08:00
}
2020-10-11 01:37:19 +08:00
auto klist = m_kdataDriver->getKRecordList(market(), code(), query);
return klist.size() > 0 ? klist[0] : Null<KRecord>();
2020-10-08 15:46:41 +08:00
}
2020-10-03 00:02:03 +08:00
KRecordList Stock::getKRecordList(const KQuery& query) const {
KRecordList result;
2020-10-06 17:56:10 +08:00
if (isNull()) {
return result;
}
2020-10-03 23:58:04 +08:00
// 如果是在内存缓存中
2020-10-03 00:02:03 +08:00
if (m_data->pKData.find(query.kType()) != m_data->pKData.end()) {
size_t start_ix = 0, end_ix = 0;
if (query.queryType() == KQuery::DATE) {
if (!_getIndexRangeByDateFromBuffer(query, start_ix, end_ix)) {
return result;
}
} else {
2020-10-03 23:58:04 +08:00
if (query.start() < 0 || query.end() < 0) {
2020-10-05 00:07:29 +08:00
// 处理负数索引
2020-10-03 23:58:04 +08:00
if (!getIndexRange(query, start_ix, end_ix)) {
return result;
}
} else {
start_ix = query.start();
end_ix = query.end();
}
2020-10-03 00:02:03 +08:00
}
2020-10-03 23:58:04 +08:00
size_t total = m_data->pKData[query.kType()]->size();
2020-10-03 00:02:03 +08:00
if (start_ix >= end_ix || start_ix > total) {
2020-10-03 23:58:04 +08:00
HKU_WARN("Invalid param! ({}, {})", start_ix, end_ix);
2020-10-03 00:02:03 +08:00
return result;
}
size_t length = end_ix > total ? total - start_ix : end_ix - start_ix;
result.resize(length);
2020-10-03 23:58:04 +08:00
std::memcpy(&(result.front()), &((*m_data->pKData[query.kType()])[start_ix]),
2020-10-03 00:02:03 +08:00
sizeof(KRecord) * length);
} else {
2020-10-06 17:56:10 +08:00
if (query.queryType() == KQuery::DATE) {
result = m_kdataDriver->getKRecordList(m_data->m_market, m_data->m_code, query);
} else {
size_t start_ix = 0, end_ix = 0;
if (query.queryType() == KQuery::INDEX) {
if (query.start() < 0 || query.end() < 0) {
// 处理负数索引
if (!getIndexRange(query, start_ix, end_ix)) {
return result;
2020-10-05 18:04:53 +08:00
}
2020-10-06 17:56:10 +08:00
} else {
start_ix = query.start();
end_ix = query.end();
2020-10-05 18:04:53 +08:00
}
2020-10-05 00:07:29 +08:00
}
2020-10-06 17:56:10 +08:00
result = m_kdataDriver->getKRecordList(m_data->m_market, m_data->m_code,
KQuery(start_ix, end_ix, query.kType()));
2020-10-03 00:02:03 +08:00
}
}
2015-01-07 01:26:14 +08:00
return result;
}
2016-04-25 01:39:07 +08:00
DatetimeList Stock::getDatetimeList(const KQuery& query) const {
DatetimeList result;
2020-10-03 23:58:04 +08:00
KRecordList k_list = getKRecordList(query);
result.reserve(k_list.size());
for (auto& k : k_list) {
result.push_back(k.datetime);
2016-04-25 01:39:07 +08:00
}
return result;
}
2019-02-11 16:33:55 +08:00
TimeLineList Stock::getTimeLineList(const KQuery& query) const {
return m_kdataDriver ? m_kdataDriver->getTimeLineList(market(), code(), query) : TimeLineList();
2019-02-08 22:41:20 +08:00
}
2019-02-11 21:13:06 +08:00
TransList Stock::getTransList(const KQuery& query) const {
return m_kdataDriver ? m_kdataDriver->getTransList(market(), code(), query) : TransList();
2019-02-11 21:13:06 +08:00
}
Parameter Stock::getFinanceInfo() const {
Parameter result;
if (type() != STOCKTYPE_A) {
return result;
}
BaseInfoDriverPtr driver = StockManager::instance().getBaseInfoDriver();
if (driver) {
result = driver->getFinanceInfo(market(), code());
}
2019-11-10 03:27:57 +08:00
return result;
}
2019-04-06 02:40:53 +08:00
PriceList Stock::getHistoryFinanceInfo(const Datetime& date) const {
if (type() == STOCKTYPE_A) {
StockManager& sm = StockManager::instance();
HistoryFinanceReader rd(sm.datadir() + "/downloads/finance");
return rd.getHistoryFinanceInfo(date, market(), code());
}
return PriceList();
}
2016-04-03 00:08:31 +08:00
void Stock::realtimeUpdate(const KRecord& record) {
2019-11-10 03:27:57 +08:00
// if (!m_data || !m_data->pKData[KQuery::DAY] ||
if (!isBuffer(KQuery::DAY) || record.datetime == Null<Datetime>()) {
2016-04-03 00:08:31 +08:00
return;
}
if (m_data->pKData[KQuery::DAY]->empty()) {
m_data->pKData[KQuery::DAY]->push_back(record);
return;
}
2019-11-10 03:27:57 +08:00
KRecord& tmp = m_data->pKData[KQuery::DAY]->back();
2016-04-03 00:08:31 +08:00
if (tmp.datetime == record.datetime) {
tmp = record;
} else if (tmp.datetime < record.datetime) {
2016-04-03 00:08:31 +08:00
m_data->pKData[KQuery::DAY]->push_back(record);
} else {
HKU_INFO("Ignore record, datetime < last record.datetime!");
2016-04-03 00:08:31 +08:00
}
}
2019-03-03 20:47:28 +08:00
Stock HKU_API getStock(const string& querystr) {
2019-11-10 19:45:57 +08:00
const StockManager& sm = StockManager::instance();
2019-03-03 20:47:28 +08:00
return sm.getStock(querystr);
}
2019-11-10 03:27:57 +08:00
} // namespace hku