支持分时线

This commit is contained in:
fasiondog 2019-02-10 21:26:02 +08:00
parent 3dce3974b5
commit 4e797c266b
16 changed files with 431 additions and 21 deletions

View File

@ -643,11 +643,9 @@ DatetimeList Stock::getDatetimeList(const KQuery& query) const {
}
TimeLine Stock::getTimeLine(const Datetime& start, const Datetime& end) {
if (isNull()) {
return TimeLine();
}
return m_kdataDriver->getTimeLine(market(), code(), start, end);
TimeLine Stock::getTimeLine(const KQuery& query) const {
return isNull() ? TimeLine()
:m_kdataDriver->getTimeLine(market(), code(), query);
}

View File

@ -156,7 +156,7 @@ public:
DatetimeList getDatetimeList(const KQuery& query) const;
/** 获取分时线 */
TimeLine getTimeLine(const Datetime& start, const Datetime& end);
TimeLine getTimeLine(const KQuery& query) const;
/** 设置权息信息 */
void setWeightList(const StockWeightList&);

View File

@ -13,7 +13,7 @@ HKU_API std::ostream & operator<<(std::ostream& os, const TimeLineRecord& record
string strip(", ");
os << std::fixed;
os.precision(4);
os << "TimeSharingRecord(Datetime(" << record.datetime.number() << ")"<< strip
os << "TimeLineRecord(Datetime(" << record.datetime.number() << ")"<< strip
<< record.price << strip
<< record.vol << ")";
os.unsetf(std::ostream::floatfield);

View File

@ -92,11 +92,11 @@ getKRecord(const string& market, const string& code,
}
TimeLine KDataDriver::getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end) {
const KQuery& query) {
HKU_INFO("This driver not support time-line!");
return TimeLine();
}
} /* namespace hku */

View File

@ -84,8 +84,15 @@ public:
virtual KRecord getKRecord(const string& market, const string& code,
size_t pos, KQuery::KType kType);
/**
* 线
* @param market
* @param code
* @param query
* @return
*/
virtual TimeLine getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end);
const KQuery& query);
private:
bool checkType();

View File

@ -781,8 +781,86 @@ _getOtherIndexRangeByDate(const string& market, const string& code,
}
TimeLine H5KDataDriver::getTimeLine(const string& market, const string& code,
const KQuery& query) {
return query.queryType() == KQuery::INDEX
? _getTimeLine(market, code, query.start(), query.end())
: _getTimeLine(market, code,
query.startDatetime(), query.endDatetime());
}
TimeLine H5KDataDriver::_getTimeLine(const string& market, const string& code,
hku_int64 start_ix, hku_int64 end_ix) {
TimeLine result;
H5FilePtr h5file;
H5::Group group;
if (!_getH5FileAndGroup(market, code, "TIME", h5file, group)) {
return result;
}
H5TimeLineRecord *pBuf=NULL;
try{
string tablename(market + code);
H5::DataSet dataset(group.openDataSet(tablename));
H5::DataSpace dataspace = dataset.getSpace();
size_t all_total = dataspace.getSelectNpoints();
if (0 == all_total) {
return result;
}
if(start_ix < 0) {
start_ix += all_total;
if(start_ix < 0)
start_ix = 0;
}
if(end_ix < 0) {
end_ix += all_total;
if(end_ix < 0)
end_ix = 0;
}
if (start_ix >= end_ix) {
return result;
}
size_t startpos = boost::numeric_cast<size_t>(start_ix);
size_t endpos = boost::numeric_cast<size_t>(end_ix);
size_t total = endpos > all_total ? all_total - startpos : endpos - startpos;
pBuf = new H5TimeLineRecord[total];
H5ReadTimeLineRecords(dataset, start_ix, total, pBuf);
TimeLineRecord record;
result.reserve(total + 2);
for(hsize_t i=0; i<total; i++){
record.datetime = Datetime(pBuf[i].datetime);
record.price = price_t(pBuf[i].price)*0.001;
record.vol = price_t(pBuf[i].vol);
result.push_back(record);
}
} catch (std::out_of_range& e) {
HKU_WARN("[H5KDataDriver::_getTimeLine] Invalid date! market_code("
<< market << code << ") "
<< e.what());
} catch (boost::bad_numeric_cast&) {
HKU_WARN("You may be use 32bit system, but data is to larger! "
"[H5KDataDriver::_getTimeLine]");
} catch (...) {
}
delete [] pBuf;
return result;
}
TimeLine H5KDataDriver
::getTimeLine(const string& market, const string& code,
::_getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end) {
TimeLine result;
if (start >= end || start > Datetime::max()) {

View File

@ -29,7 +29,7 @@ public:
virtual KRecord getKRecord(const string& market, const string& code,
size_t pos, KQuery::KType kType);
virtual TimeLine getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end);
const KQuery& query);
private:
void H5ReadRecords(H5::DataSet&, hsize_t, hsize_t, void *);
@ -57,6 +57,12 @@ private:
bool _getOtherIndexRangeByDate(const string&, const string&, const KQuery&,
size_t& out_start, size_t& out_end);
TimeLine _getTimeLine(const string& market, const string& code,
hku_int64 start, hku_int64 end);
TimeLine _getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end);
private:
H5::CompType m_h5DataType;
H5::CompType m_h5IndexType;

View File

@ -2,10 +2,10 @@
#define HKU_H
// version
#define HKU_VERSION "1.0.9"
#define HKU_VERSION "1.1.0"
#define HKU_VERSION_MAJOR 1
#define HKU_VERSION_MINOR 0
#define HKU_VERSION_ALTER 9
#define HKU_VERSION_MINOR 1
#define HKU_VERSION_ALTER 0
// defines
#define HKU_PACKAGE_HAVE_HDF5 1

View File

@ -0,0 +1,199 @@
/*
* test_TimeLine.cpp
*
* Created on: 2019210
* Author: fasiondog
*/
#ifdef TEST_ALL_IN_ONE
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_MODULE test_hikyuu_base
#include <boost/test/unit_test.hpp>
#endif
#include <hikyuu/StockManager.h>
#include <hikyuu/Stock.h>
using namespace hku;
/**
* @defgroup test_hikyuu_TimeLine test_hikyuu_TimeLine
* @ingroup test_hikyuu_base_suite
* @{
*/
/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_TimeLine_query_by_index ) {
StockManager& sm = StockManager::instance();
Stock stock = sm["sz000001"];
KQuery query;
TimeLine result;
/** @arg start == end > 0*/
query = KQuery(1, 1);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start == end < 0*/
query = KQuery(-1, -1);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start == end == 0*/
query = KQuery(-1, -1);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start > end > 0*/
query = KQuery(1, 3);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201812030931), 10.57, 26962));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201812030932), 10.53, 15407));
/** @arg start < end < 0*/
query = KQuery(-3, -1);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
/** @arg start < end == 0*/
query = KQuery(-3, 0);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg 未指定start, end*/
query = KQuery();
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 10320);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201812030930), 10.61, 83391));
BOOST_CHECK(result[6516] == TimeLineRecord(Datetime(201901111006), 10.18, 2823));
BOOST_CHECK(result[10319] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg 未指定end*/
query = KQuery(-3);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
query = KQuery(10317);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg end 等于总数*/
query = KQuery(10317, 10320);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg end 比总数少1*/
query = KQuery(10317, 10319);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
/** @arg end 大于总数*/
query = KQuery(10317, 10321);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg start 等于总数*/
query = KQuery(10320);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start 比总数少1*/
query = KQuery(10319);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 1);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg start 大于总数*/
query = KQuery(10321);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start>0, end<0, 且两者有交集*/
query = KQuery(10317, -1);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
/** @arg start<0, end>0, 且两者有交集*/
query = KQuery(-3, 10319);
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
}
/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_TimeLine_query_by_date ) {
StockManager& sm = StockManager::instance();
Stock stock = sm["sz000001"];
KQuery query;
TimeLine result;
/** @arg start 小于数据起始日期未指定end*/
query = KQueryByDate(Datetime(201812030000));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 10320);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201812030930), 10.61, 83391));
BOOST_CHECK(result[6516] == TimeLineRecord(Datetime(201901111006), 10.18, 2823));
BOOST_CHECK(result[10319] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg start 等于数据起始日期未指定end*/
query = KQueryByDate(Datetime(201812030930));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 10320);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201812030930), 10.61, 83391));
BOOST_CHECK(result[6516] == TimeLineRecord(Datetime(201901111006), 10.18, 2823));
BOOST_CHECK(result[10319] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg start大于数据起始日期未指定end*/
query = KQueryByDate(Datetime(201902011457));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
/** @arg start 等于 end*/
query = KQueryByDate(Datetime(201902011457), Datetime(201902011457));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 0);
/** @arg start, end 都在数据范围内, 且end为最后一条记录日期 */
query = KQueryByDate(Datetime(201902011457), Datetime(201902011459));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 2);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
/** @arg start 在数据范围内, end大于最后一条记录日期 */
query = KQueryByDate(Datetime(201902011457), Datetime(201902020000));
result = stock.getTimeLine(query);
BOOST_CHECK(result.size() == 3);
BOOST_CHECK(result[0] == TimeLineRecord(Datetime(201902011457), 11.20, 46));
BOOST_CHECK(result[1] == TimeLineRecord(Datetime(201902011458), 11.20, 0));
BOOST_CHECK(result[2] == TimeLineRecord(Datetime(201902011459), 11.20, 20572));
}
/** @} */

View File

@ -0,0 +1,92 @@
/*
* test_TimeLine.cpp
*
* Created on: 2019210
* Author: fasiondog
*/
#ifdef TEST_ALL_IN_ONE
#include <boost/test/unit_test.hpp>
#else
#define BOOST_TEST_MODULE test_hikyuu_serialize_suite
#include <boost/test/unit_test.hpp>
#endif
#include <fstream>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <hikyuu/StockManager.h>
#include <hikyuu/serialization/TimeLineRecord_serialization.h>
using namespace hku;
#if HKU_SUPPORT_SERIALIZATION
/**
* @defgroup test_TimeLine_serialize test_TimeLine_serialize
* @ingroup test_hikyuu_serialize_suite
* @{
*/
/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_TimeLineRecord_serialize ) {
string filename(StockManager::instance().tmpdir());
filename += "/TimeLineRecord.xml";
TimeLineRecord t1(Datetime(201101010000), 10.0, 80);
{
std::ofstream ofs(filename);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(t1);
}
TimeLineRecord t2;
{
std::ifstream ifs(filename);
boost::archive::xml_iarchive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(t2);
}
BOOST_CHECK(t1.datetime == t2.datetime);
BOOST_CHECK(t1.price == t2.price);
BOOST_CHECK(t1.vol == t2.vol);
}
/** @par 检测点 */
BOOST_AUTO_TEST_CASE( test_TimeLine_serialize ) {
string filename(StockManager::instance().tmpdir());
filename += "/TimeLine.xml";
TimeLine line1;
line1.push_back(TimeLineRecord(Datetime(201101010000), 10.0, 80));
line1.push_back(TimeLineRecord(Datetime(201101020000), 20.0, 90));
line1.push_back(TimeLineRecord(Datetime(201101030000), 20.0, 100));
{
std::ofstream ofs(filename);
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(line1);
}
TimeLine line2;
{
std::ifstream ifs(filename);
boost::archive::xml_iarchive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(line2);
}
BOOST_CHECK(line1.size() != 0);
BOOST_CHECK(line1.size() == line2.size());
size_t total = line1.size();
for (size_t i = 0; i < total; i++) {
BOOST_CHECK(line1[i] == line2[i]);
}
}
/** @} */
#endif /* HKU_SUPPORT_SERIALIZATION */

View File

@ -378,6 +378,8 @@ __all__ = [#类
'KQueryByIndex',
'KRecord',
'KRecordList',
'TimeLineRecord',
'TimeLine',
'MarketInfo',
'Parameter',
'PriceList',

View File

@ -704,6 +704,21 @@ tocsv(filename)
"""
#------------------------------------------------------------------
# from _Stock.cpp
#------------------------------------------------------------------
TimeLineRecord.__doc__ = """分时线记录,属性可读写。"""
TimeLineRecord.datetime.__doc__ = """时间"""
TimeLineRecord.price.__doc__ = """价格"""
TimeLineRecord.vol.__doc__ = """成交量"""
TimeLine.__doc__ = """
Stock.getTimeLine 线 TimeLineRecord list
"""
#------------------------------------------------------------------
# from _Stock.cpp
#------------------------------------------------------------------
@ -815,6 +830,15 @@ getDatetimeList(start, end, ktype)
:rtype: DatetimeList
"""
Stock.getTimeLine.__doc__ = """
getTimeLine(self, query)
线
:param Query query: K线类型
:rtype: TimeLine
"""
Stock.getWeight.__doc__ = """
getWeight([start, end])

View File

@ -135,17 +135,17 @@ public:
}
TimeLine getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end) {
const KQuery& query) {
if (override call = get_override("getTimeLine")) {
return call(market, code, start, end);
return call(market, code, query);
} else {
return KDataDriver::getTimeLine(market, code, start, end);
return KDataDriver::getTimeLine(market, code, query);
}
}
TimeLine default_getTimeLine(const string& market, const string& code,
const Datetime& start, const Datetime& end) {
return this->KDataDriver::getTimeLine(market, code, start, end);
const KQuery& query) {
return this->KDataDriver::getTimeLine(market, code, query);
}
};

View File

@ -30,3 +30,5 @@ sh_min5 = ./test_data/sh_5min.h5
sz_day = ./test_data/sz_day.h5
sz_min = ./test_data/sz_1min.h5
sz_min5 = ./test_data/sz_5min.h5
sh_time = ./test_data/sh_time.h5
sz_time = ./test_data/sz_time.h5

View File

@ -31,3 +31,5 @@ sh_min5 = .\\test_data\\sh_5min.h5
sz_day = .\\test_data\\sz_day.h5
sz_min = .\\test_data\\sz_1min.h5
sz_min5 = .\\test_data\\sz_5min.h5
sh_time = .\\test_data\\sh_time.h5
sz_time = .\\test_data\\sz_time.h5

View File

@ -4,7 +4,7 @@ set_xmakever("2.2.2")
set_project("hikyuu")
-- version
set_version("1.0.9")
set_version("1.1.0")
-- set warning all as error
set_warnings("all", "error")