Merge branch 'master' of https://github.com/fasiondog/hikyuu into feature/fastind

This commit is contained in:
fasiondog 2023-10-29 19:05:24 +08:00
commit 6ad36dcf62
20 changed files with 219 additions and 81 deletions

View File

@ -319,6 +319,7 @@ class HubManager(metaclass=SingletonType):
'st': 'part/st', 'st': 'part/st',
'prtflo': 'prtflo', 'prtflo': 'prtflo',
'sys': 'sys', 'sys': 'sys',
'ind': 'ind',
} }
# 检查仓库本地目录是否存在,不存在则给出告警信息并直接返回 # 检查仓库本地目录是否存在,不存在则给出告警信息并直接返回
@ -340,7 +341,7 @@ class HubManager(metaclass=SingletonType):
if (not entry.name.startswith('.')) and entry.is_dir() and (entry.name != "__pycache__"): if (not entry.name.startswith('.')) and entry.is_dir() and (entry.name != "__pycache__"):
# 计算实际的导入模块名 # 计算实际的导入模块名
module_name = '{}.part.{}.{}.part'.format(base_local, part, entry.name) if part not in ( module_name = '{}.part.{}.{}.part'.format(base_local, part, entry.name) if part not in (
'prtflo', 'sys' 'prtflo', 'sys', 'ind'
) else '{}.{}.{}.part'.format(base_local, part, entry.name) ) else '{}.{}.{}.part'.format(base_local, part, entry.name)
# 导入模块 # 导入模块
@ -359,7 +360,7 @@ class HubManager(metaclass=SingletonType):
continue continue
name = '{}.{}.{}'.format(hub_model.name, part, entry.name) if part not in ( name = '{}.{}.{}'.format(hub_model.name, part, entry.name) if part not in (
'prtflo', 'sys' 'prtflo', 'sys', 'ind'
) else '{}.{}.{}'.format(hub_model.name, part, entry.name) ) else '{}.{}.{}'.format(hub_model.name, part, entry.name)
try: try:
@ -390,8 +391,8 @@ class HubManager(metaclass=SingletonType):
name_parts = name.split('.') name_parts = name.split('.')
checkif( checkif(
len(name_parts) < 2 len(name_parts) < 2
or (name_parts[-2] not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys')), name, or (name_parts[-2] not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys', 'ind')),
PartNameError name, PartNameError
) )
# 未指定仓库名,则默认使用 'default' 仓库 # 未指定仓库名,则默认使用 'default' 仓库
@ -403,8 +404,11 @@ class HubManager(metaclass=SingletonType):
except ModuleNotFoundError: except ModuleNotFoundError:
raise PartNotFoundError(part_name, '') raise PartNotFoundError(part_name, '')
part = part_module.part(**kwargs) part = part_module.part(**kwargs)
part.name = part_model.name try:
part.info = self.get_part_info(part.name) part.name = part_model.name
part.info = self.get_part_info(part.name)
except:
pass
return part return part
@dbsession @dbsession
@ -477,7 +481,7 @@ class HubManager(metaclass=SingletonType):
""" """
abs_path = os.path.abspath(filename) # abs_path = os.path.abspath(filename) #
path_parts = pathlib.Path(abs_path).parts path_parts = pathlib.Path(abs_path).parts
local_base = path_parts[-4] if path_parts[-3] in ('prtflo', 'sys') else path_parts[5] local_base = path_parts[-4] if path_parts[-3] in ('prtflo', 'sys', 'ind') else path_parts[5]
hub_model = self._session.query(HubModel.name).filter_by(local_base=local_base).first() hub_model = self._session.query(HubModel.name).filter_by(local_base=local_base).first()
checkif(hub_model is None, local_base, HubNotFoundError) checkif(hub_model is None, local_base, HubNotFoundError)
return hub_model.name return hub_model.name
@ -592,10 +596,13 @@ if __name__ == "__main__":
logging.basicConfig( logging.basicConfig(
level=logging.INFO, format='%(asctime)-15s [%(levelname)s] - %(message)s [%(name)s::%(funcName)s]' level=logging.INFO, format='%(asctime)-15s [%(levelname)s] - %(message)s [%(name)s::%(funcName)s]'
) )
add_local_hub('dev', '/home/fasiondog/workspace/stockhouse') # add_local_hub('dev', '/home/fasiondog/workspace/stockhouse')
remove_hub('dev')
add_local_hub('dev', r'D:\workspace\hikyuu_hub')
#update_hub('test1') #update_hub('test1')
update_hub('default') update_hub('default')
sg = get_part('dev.st.fixed_percent') # sg = get_part('dev.st.fixed_percent')
sg = get_part('dev.ind.')
print(sg) print(sg)
print_part_info('default.sp.fixed_value') # print_part_info('default.sp.fixed_value')
print(get_part_name_list(part_type='sg')) # print(get_part_name_list(part_type='sg'))

View File

@ -34,9 +34,7 @@ public:
bool empty() const; bool empty() const;
bool operator==(const KData&) const; bool operator==(const KData&) const;
bool operator!=(const KData& other) const { bool operator!=(const KData&) const;
return !(*this == other);
}
DatetimeList getDatetimeList() const; DatetimeList getDatetimeList() const;
@ -220,6 +218,10 @@ inline size_t KData::lastPos() const {
return m_imp ? m_imp->lastPos() : 0; return m_imp ? m_imp->lastPos() : 0;
} }
inline bool KData::operator!=(const KData& other) const {
return !(*this == other);
}
} /* namespace hku */ } /* namespace hku */
#if FMT_VERSION >= 90000 #if FMT_VERSION >= 90000

View File

@ -29,29 +29,29 @@ const string KQuery::HOUR12("HOUR12");
// const string KQuery::INVALID_KTYPE("Z"); // const string KQuery::INVALID_KTYPE("Z");
static vector<string> g_all_ktype{KQuery::MIN, KQuery::MIN5, KQuery::MIN15, KQuery::MIN30, static vector<string> g_all_ktype{KQuery::MIN, KQuery::MIN5, KQuery::MIN15, KQuery::MIN30,
KQuery::MIN60, KQuery::DAY, KQuery::WEEK, KQuery::MONTH, KQuery::MIN60, KQuery::DAY, KQuery::WEEK, KQuery::MONTH,
KQuery::QUARTER, KQuery::HALFYEAR, KQuery::YEAR, KQuery::MIN3, KQuery::QUARTER, KQuery::HALFYEAR, KQuery::YEAR, KQuery::MIN3,
KQuery::HOUR2, KQuery::HOUR4, KQuery::HOUR6, KQuery::HOUR12}; KQuery::HOUR2, KQuery::HOUR4, KQuery::HOUR6, KQuery::HOUR12};
static const unordered_map<string, int32_t> g_ktype2min{ static const unordered_map<string, int32_t> g_ktype2min{
{KQuery::MIN, 1}, {KQuery::MIN, 1},
{KQuery::MIN3, 3}, {KQuery::MIN3, 3},
{KQuery::MIN5, 5}, {KQuery::MIN5, 5},
{KQuery::MIN15, 15}, {KQuery::MIN15, 15},
{KQuery::MIN30, 30}, {KQuery::MIN30, 30},
{KQuery::MIN60, 60}, {KQuery::MIN60, 60},
{KQuery::HOUR2, 60 * 2}, {KQuery::HOUR2, 60 * 2},
{KQuery::HOUR4, 60 * 4}, {KQuery::HOUR4, 60 * 4},
{KQuery::HOUR6, 60 * 6}, {KQuery::HOUR6, 60 * 6},
{KQuery::HOUR12, 60 * 12}, {KQuery::HOUR12, 60 * 12},
{KQuery::DAY, 60 * 24}, {KQuery::DAY, 60 * 24},
{KQuery::WEEK, 60 * 24 * 7}, {KQuery::WEEK, 60 * 24 * 7},
{KQuery::MONTH, 60 * 24 * 30}, {KQuery::MONTH, 60 * 24 * 30},
{KQuery::QUARTER, 60 * 24 * 30 * 3}, {KQuery::QUARTER, 60 * 24 * 30 * 3},
{KQuery::HALFYEAR, 60 * 24 * 30 * 6}, {KQuery::HALFYEAR, 60 * 24 * 30 * 6},
{KQuery::YEAR, 60 * 24 * 365}, {KQuery::YEAR, 60 * 24 * 365},
}; };
// 获取所有的 KType // 获取所有的 KType
@ -163,4 +163,16 @@ HKU_API std::ostream& operator<<(std::ostream& os, const KQuery& query) {
return os; return os;
} }
bool HKU_API operator!=(const KQuery& q1, const KQuery& q2) {
// cppcheck-suppress [mismatchingContainerExpression]
return q1.start() != q2.start() || q1.end() != q2.end() || q1.queryType() != q2.queryType() ||
q1.kType() != q2.kType() || q1.recoverType() != q2.recoverType();
}
bool HKU_API operator==(const KQuery& q1, const KQuery& q2) {
// cppcheck-suppress [mismatchingContainerExpression]
return q1.start() == q2.start() && q1.end() == q2.end() && q1.queryType() == q2.queryType() &&
q1.kType() == q2.kType() && q1.recoverType() == q2.recoverType();
}
} // namespace hku } // namespace hku

View File

@ -244,18 +244,8 @@ HKU_API std::ostream& operator<<(std::ostream& os, const KQuery& query);
// 关系比较函数, 不直接在类中定义是为了支持 Null<>() == dNull可以放在左边 // 关系比较函数, 不直接在类中定义是为了支持 Null<>() == dNull可以放在左边
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool operator==(const KQuery&, const KQuery&); bool HKU_API operator==(const KQuery&, const KQuery&);
bool operator!=(const KQuery&, const KQuery&); bool HKU_API operator!=(const KQuery&, const KQuery&);
inline bool operator!=(const KQuery& q1, const KQuery& q2) {
// cppcheck-suppress [mismatchingContainerExpression]
return q1.start() != q2.start() || q1.end() != q2.end() || q1.queryType() != q2.queryType() ||
q1.kType() != q2.kType() || q1.recoverType() != q2.recoverType();
}
inline bool operator==(const KQuery& q1, const KQuery& q2) {
return !(q1 != q2);
}
/** /**
* KQuery的Null值 * KQuery的Null值

View File

@ -30,4 +30,8 @@ bool HKU_API operator==(const KRecord& d1, const KRecord& d2) {
(std::fabs(d1.transCount - d2.transCount) < 0.0001)); (std::fabs(d1.transCount - d2.transCount) < 0.0001));
} }
bool HKU_API operator!=(const KRecord& d1, const KRecord& d2) {
return !(d1 == d2);
}
} // namespace hku } // namespace hku

View File

@ -78,6 +78,12 @@ HKU_API std::ostream& operator<<(std::ostream&, const KRecord&);
*/ */
bool HKU_API operator==(const KRecord& d1, const KRecord& d2); bool HKU_API operator==(const KRecord& d1, const KRecord& d2);
/**
* KRecord不等比较
* @ingroup StockManage
*/
bool HKU_API operator!=(const KRecord& d1, const KRecord& d2);
} // namespace hku } // namespace hku
#if FMT_VERSION >= 90000 #if FMT_VERSION >= 90000

View File

@ -158,12 +158,10 @@ Stock::Stock(const string& market, const string& code, const string& name, uint3
: m_data(make_shared<Data>(market, code, name, type, valid, startDate, lastDate, tick, tickValue, : m_data(make_shared<Data>(market, code, name, type, valid, startDate, lastDate, tick, tickValue,
precision, minTradeNumber, maxTradeNumber)) {} precision, minTradeNumber, maxTradeNumber)) {}
bool Stock::operator!=(const Stock& stock) const { bool Stock::operator==(const Stock& stock) const {
HKU_IF_RETURN(this == &stock, false); return this == &stock || m_data == stock.m_data ||
HKU_IF_RETURN(m_data == stock.m_data, false); (m_data && stock.m_data && (m_data->m_code == stock.m_data->m_code) &&
HKU_IF_RETURN(!m_data || !stock.m_data, true); (m_data->m_market == stock.m_data->m_market));
HKU_IF_RETURN(m_data->m_code != stock.code() || m_data->m_market != stock.market(), true);
return false;
} }
const string& Stock::market() const { const string& Stock::market() const {

View File

@ -233,14 +233,14 @@ private:
}; };
struct HKU_API Stock::Data { struct HKU_API Stock::Data {
string m_market; // 所属的市场简称 string m_market; // 所属的市场简称
string m_code; // 证券代码 string m_code; // 证券代码
string m_market_code; // 市场简称证券代码 string m_market_code; // 市场简称证券代码
string m_name; // 证券名称 string m_name; // 证券名称
uint32_t m_type; // 证券类型 uint32_t m_type; // 证券类型
bool m_valid; // 当前证券是否有效 bool m_valid; // 当前证券是否有效
Datetime m_startDate; // 证券起始日期 Datetime m_startDate; // 证券起始日期
Datetime m_lastDate; // 证券最后日期 Datetime m_lastDate; // 证券最后日期
StockWeightList m_weightList; // 权息信息列表 StockWeightList m_weightList; // 权息信息列表
std::mutex m_weight_mutex; std::mutex m_weight_mutex;
@ -291,8 +291,8 @@ inline uint64_t Stock::id() const {
return isNull() ? 0 : (int64_t)m_data.get(); return isNull() ? 0 : (int64_t)m_data.get();
} }
inline bool Stock::operator==(const Stock& stock) const { inline bool Stock::operator!=(const Stock& stock) const {
return (*this != stock) ? false : true; return !(*this == stock);
} }
} // namespace hku } // namespace hku

View File

@ -20,6 +20,88 @@ namespace hku {
StealThreadPool *IndicatorImp::ms_tg = nullptr; StealThreadPool *IndicatorImp::ms_tg = nullptr;
string HKU_API getOPTypeName(IndicatorImp::OPType op) {
string name;
switch (op) {
case IndicatorImp::LEAF:
name = "LEAF";
break;
case IndicatorImp::OP:
name = "OP";
break;
case IndicatorImp::ADD:
name = "ADD";
break;
case IndicatorImp::SUB:
name = "SUB";
break;
case IndicatorImp::MUL:
name = "MUL";
break;
case IndicatorImp::DIV:
name = "DIV";
break;
case IndicatorImp::MOD:
name = "MOD";
break;
case IndicatorImp::EQ:
name = "EQ";
break;
case IndicatorImp::GT:
name = "GT";
break;
case IndicatorImp::LT:
name = "LT";
break;
case IndicatorImp::NE:
name = "NE";
break;
case IndicatorImp::GE:
name = "GE";
break;
case IndicatorImp::LE:
name = "LE";
break;
case IndicatorImp::AND:
name = "AND";
break;
case IndicatorImp::OR:
name = "OR";
break;
case IndicatorImp::WEAVE:
name = "WEAVE";
break;
case IndicatorImp::OP_IF:
name = "IF";
break;
case IndicatorImp::CORR:
name = "CORR";
break;
default:
name = "UNKNOWN";
break;
}
return name;
}
void IndicatorImp::initDynEngine() { void IndicatorImp::initDynEngine() {
auto cpu_num = std::thread::hardware_concurrency(); auto cpu_num = std::thread::hardware_concurrency();
if (cpu_num > 32) { if (cpu_num > 32) {
@ -501,6 +583,10 @@ void IndicatorImp::add(OPType op, IndicatorImpPtr left, IndicatorImpPtr right) {
m_three->m_parent = this; m_three->m_parent = this;
} }
if (m_name == "IndicatorImp") {
m_name = getOPTypeName(op);
}
repeatALikeNodes(); repeatALikeNodes();
} }
@ -514,6 +600,9 @@ void IndicatorImp::add_if(IndicatorImpPtr cond, IndicatorImpPtr left, IndicatorI
m_three->m_parent = this; m_three->m_parent = this;
m_left->m_parent = this; m_left->m_parent = this;
m_right->m_parent = this; m_right->m_parent = this;
if (m_name == "IndicatorImp") {
m_name = getOPTypeName(IndicatorImp::OP_IF);
}
repeatALikeNodes(); repeatALikeNodes();
} }

View File

@ -376,6 +376,9 @@ public: \
return true; \ return true; \
} }
/** 获取 OPType 名称字符串 */
string HKU_API getOPTypeName(IndicatorImp::OPType);
typedef shared_ptr<IndicatorImp> IndicatorImpPtr; typedef shared_ptr<IndicatorImp> IndicatorImpPtr;
HKU_API std::ostream& operator<<(std::ostream&, const IndicatorImp&); HKU_API std::ostream& operator<<(std::ostream&, const IndicatorImp&);

View File

@ -43,6 +43,7 @@ public:
m_driver->commit(); m_driver->commit();
} catch (...) { } catch (...) {
HKU_ERROR("Transaction commit failed!"); HKU_ERROR("Transaction commit failed!");
m_driver->rollback();
m_driver.reset(); m_driver.reset();
} }
} }

View File

@ -28,12 +28,12 @@ class SQLResultSet;
class HKU_API DBConnectBase : public std::enable_shared_from_this<DBConnectBase> { class HKU_API DBConnectBase : public std::enable_shared_from_this<DBConnectBase> {
PARAMETER_SUPPORT // NOSONAR PARAMETER_SUPPORT // NOSONAR
public: public :
/** /**
* *
* @param param * @param param
*/ */
explicit DBConnectBase(const Parameter &param); explicit DBConnectBase(const Parameter &param);
virtual ~DBConnectBase() = default; virtual ~DBConnectBase() = default;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -50,7 +50,7 @@ public:
virtual void commit() = 0; virtual void commit() = 0;
/** 回滚事务 */ /** 回滚事务 */
virtual void rollback() = 0; virtual void rollback() noexcept = 0;
/** 执行无返回结果的 SQL */ /** 执行无返回结果的 SQL */
virtual int64_t exec(const std::string &sql_string) = 0; virtual int64_t exec(const std::string &sql_string) = 0;

View File

@ -157,8 +157,14 @@ void MySQLConnect::commit() {
exec("COMMIT"); exec("COMMIT");
} }
void MySQLConnect::rollback() { void MySQLConnect::rollback() noexcept {
exec("ROLLBACK"); try {
exec("ROLLBACK");
} catch (const std::exception& e) {
HKU_ERROR("rollback failed! {}", e.what());
} catch (...) {
HKU_ERROR("Unknonw error!");
}
} }
} // namespace hku } // namespace hku

View File

@ -39,7 +39,7 @@ public:
virtual void transaction() override; virtual void transaction() override;
virtual void commit() override; virtual void commit() override;
virtual void rollback() override; virtual void rollback() noexcept override;
private: private:
void close(); void close();

View File

@ -16,12 +16,12 @@
namespace hku { namespace hku {
// sqlite3 多线程处理时,等待其他锁释放回调处理 // sqlite3 多线程处理时,等待其他锁释放回调处理
static int sqlite_busy_call_back(void* ptr, int count) { static int sqlite_busy_call_back(void *ptr, int count) {
std::this_thread::yield(); std::this_thread::yield();
return 1; return 1;
} }
SQLiteConnect::SQLiteConnect(const Parameter& param) : DBConnectBase(param), m_db(nullptr) { SQLiteConnect::SQLiteConnect(const Parameter &param) : DBConnectBase(param), m_db(nullptr) {
try { try {
m_dbname = getParam<string>("db"); m_dbname = getParam<string>("db");
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX; int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX;
@ -50,16 +50,16 @@ SQLiteConnect::SQLiteConnect(const Parameter& param) : DBConnectBase(param), m_d
sqlite3_extended_result_codes(m_db, true); sqlite3_extended_result_codes(m_db, true);
} }
} catch (std::out_of_range& e) { } catch (std::out_of_range &e) {
HKU_FATAL("Can't get database name! {}", e.what()); HKU_FATAL("Can't get database name! {}", e.what());
close(); close();
throw; throw;
} catch (SQLException& e) { } catch (SQLException &e) {
HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname, HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname,
e.errcode(), e.what()); e.errcode(), e.what());
close(); close();
throw; throw;
} catch (std::exception& e) { } catch (std::exception &e) {
HKU_FATAL("Failed initialize data driver({})! exception: {}", m_dbname, e.what()); HKU_FATAL("Failed initialize data driver({})! exception: {}", m_dbname, e.what());
close(); close();
throw; throw;
@ -108,15 +108,21 @@ void SQLiteConnect::commit() {
exec("COMMIT TRANSACTION"); exec("COMMIT TRANSACTION");
} }
void SQLiteConnect::rollback() { void SQLiteConnect::rollback() noexcept {
exec("ROLLBACK TRANSACTION"); try {
exec("ROLLBACK TRANSACTION");
} catch (const std::exception &e) {
HKU_ERROR("rollback failed! {}", e.what());
} catch (...) {
HKU_ERROR("Unknown error!");
}
} }
SQLStatementPtr SQLiteConnect::getStatement(const std::string &sql_statement) { SQLStatementPtr SQLiteConnect::getStatement(const std::string &sql_statement) {
return std::make_shared<SQLiteStatement>(this, sql_statement); return std::make_shared<SQLiteStatement>(this, sql_statement);
} }
bool SQLiteConnect::tableExist(const string& tablename) { bool SQLiteConnect::tableExist(const string &tablename) {
SQLStatementPtr st = SQLStatementPtr st =
getStatement(fmt::format("select count(1) from sqlite_master where name='{}'", tablename)); getStatement(fmt::format("select count(1) from sqlite_master where name='{}'", tablename));
st->exec(); st->exec();

View File

@ -47,7 +47,7 @@ public:
virtual void transaction() override; virtual void transaction() override;
virtual void commit() override; virtual void commit() override;
virtual void rollback() override; virtual void rollback() noexcept override;
virtual int64_t exec(const std::string &sql_string) override; virtual int64_t exec(const std::string &sql_string) override;
virtual SQLStatementPtr getStatement(const std::string &sql_statement) override; virtual SQLStatementPtr getStatement(const std::string &sql_statement) override;
virtual bool tableExist(const std::string &tablename) override; virtual bool tableExist(const std::string &tablename) override;
@ -79,7 +79,7 @@ private:
private: private:
friend class SQLiteStatement; friend class SQLiteStatement;
string m_dbname; string m_dbname;
sqlite3* m_db; sqlite3 *m_db;
}; };
typedef shared_ptr<SQLiteConnect> SQLiteConnectPtr; typedef shared_ptr<SQLiteConnect> SQLiteConnectPtr;

View File

@ -51,6 +51,7 @@ target("hikyuu")
end end
if is_plat("linux", "cross") then if is_plat("linux", "cross") then
add_cxflags("-fPIC")
if get_config("hdf5") then if get_config("hdf5") then
add_packages("hdf5") add_packages("hdf5")
end end

View File

@ -88,6 +88,10 @@ void export_KData() {
:param str filename: )") :param str filename: )")
.def("__len__", &KData::size) .def("__len__", &KData::size)
.def(self == self)
.def(self != self)
#if HKU_PYTHON_SUPPORT_PICKLE #if HKU_PYTHON_SUPPORT_PICKLE
.def_pickle(normal_pickle_suite<KData>()) .def_pickle(normal_pickle_suite<KData>())
#endif #endif

View File

@ -15,6 +15,9 @@ using namespace hku;
KQuery::RecoverType (KQuery::*get_recoverType)() const = &KQuery::recoverType; KQuery::RecoverType (KQuery::*get_recoverType)() const = &KQuery::recoverType;
void (KQuery::*set_recoverType)(KQuery::RecoverType recoverType) = &KQuery::recoverType; void (KQuery::*set_recoverType)(KQuery::RecoverType recoverType) = &KQuery::recoverType;
bool (*kquery_eq)(const KQuery&, const KQuery&) = operator==;
bool (*kquery_ne)(const KQuery&, const KQuery&) = operator!=;
void export_KQuery() { void export_KQuery() {
scope in_Query = scope in_Query =
class_<KQuery>("Query", "K线数据查询条件", init<>()) class_<KQuery>("Query", "K线数据查询条件", init<>())
@ -37,6 +40,9 @@ void export_KQuery() {
.add_property("recover_type", get_recoverType, set_recoverType, .add_property("recover_type", get_recoverType, set_recoverType,
"查询的复权类型 Query.RecoverType") "查询的复权类型 Query.RecoverType")
.def("__eq__", kquery_eq)
.def("__ne__", kquery_ne)
#if HKU_PYTHON_SUPPORT_PICKLE #if HKU_PYTHON_SUPPORT_PICKLE
.def_pickle(normal_pickle_suite<KQuery>()) .def_pickle(normal_pickle_suite<KQuery>())
#endif #endif

View File

@ -18,6 +18,7 @@ using namespace hku;
#endif #endif
bool (*krecord_eq)(const KRecord&, const KRecord&) = operator==; bool (*krecord_eq)(const KRecord&, const KRecord&) = operator==;
bool (*krecord_ne)(const KRecord&, const KRecord&) = operator!=;
void export_KReord() { void export_KReord() {
class_<KRecord>("KRecord", "K线记录组成K线数据属性可读写", init<>()) class_<KRecord>("KRecord", "K线记录组成K线数据属性可读写", init<>())
@ -35,6 +36,8 @@ void export_KReord() {
.def_readwrite("volume", &KRecord::transCount, "成交量") .def_readwrite("volume", &KRecord::transCount, "成交量")
.def("__eq__", krecord_eq) .def("__eq__", krecord_eq)
.def("__ne__", krecord_ne)
#if HKU_PYTHON_SUPPORT_PICKLE #if HKU_PYTHON_SUPPORT_PICKLE
.def_pickle(normal_pickle_suite<KRecord>()) .def_pickle(normal_pickle_suite<KRecord>())
#endif #endif