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',
'prtflo': 'prtflo',
'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__"):
# 计算实际的导入模块名
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)
# 导入模块
@ -359,7 +360,7 @@ class HubManager(metaclass=SingletonType):
continue
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)
try:
@ -390,8 +391,8 @@ class HubManager(metaclass=SingletonType):
name_parts = name.split('.')
checkif(
len(name_parts) < 2
or (name_parts[-2] not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys')), name,
PartNameError
or (name_parts[-2] not in ('af', 'cn', 'ev', 'mm', 'pg', 'se', 'sg', 'sp', 'st', 'prtflo', 'sys', 'ind')),
name, PartNameError
)
# 未指定仓库名,则默认使用 'default' 仓库
@ -403,8 +404,11 @@ class HubManager(metaclass=SingletonType):
except ModuleNotFoundError:
raise PartNotFoundError(part_name, '')
part = part_module.part(**kwargs)
part.name = part_model.name
part.info = self.get_part_info(part.name)
try:
part.name = part_model.name
part.info = self.get_part_info(part.name)
except:
pass
return part
@dbsession
@ -477,7 +481,7 @@ class HubManager(metaclass=SingletonType):
"""
abs_path = os.path.abspath(filename) #
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()
checkif(hub_model is None, local_base, HubNotFoundError)
return hub_model.name
@ -592,10 +596,13 @@ if __name__ == "__main__":
logging.basicConfig(
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('default')
sg = get_part('dev.st.fixed_percent')
# sg = get_part('dev.st.fixed_percent')
sg = get_part('dev.ind.')
print(sg)
print_part_info('default.sp.fixed_value')
print(get_part_name_list(part_type='sg'))
# print_part_info('default.sp.fixed_value')
# print(get_part_name_list(part_type='sg'))

View File

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

View File

@ -29,29 +29,29 @@ const string KQuery::HOUR12("HOUR12");
// const string KQuery::INVALID_KTYPE("Z");
static vector<string> g_all_ktype{KQuery::MIN, KQuery::MIN5, KQuery::MIN15, KQuery::MIN30,
KQuery::MIN60, KQuery::DAY, KQuery::WEEK, KQuery::MONTH,
KQuery::QUARTER, KQuery::HALFYEAR, KQuery::YEAR, KQuery::MIN3,
KQuery::HOUR2, KQuery::HOUR4, KQuery::HOUR6, KQuery::HOUR12};
KQuery::MIN60, KQuery::DAY, KQuery::WEEK, KQuery::MONTH,
KQuery::QUARTER, KQuery::HALFYEAR, KQuery::YEAR, KQuery::MIN3,
KQuery::HOUR2, KQuery::HOUR4, KQuery::HOUR6, KQuery::HOUR12};
static const unordered_map<string, int32_t> g_ktype2min{
{KQuery::MIN, 1},
{KQuery::MIN3, 3},
{KQuery::MIN, 1},
{KQuery::MIN3, 3},
{KQuery::MIN5, 5},
{KQuery::MIN15, 15},
{KQuery::MIN30, 30},
{KQuery::MIN60, 60},
{KQuery::HOUR2, 60 * 2},
{KQuery::HOUR4, 60 * 4},
{KQuery::HOUR6, 60 * 6},
{KQuery::HOUR12, 60 * 12},
{KQuery::MIN5, 5},
{KQuery::MIN15, 15},
{KQuery::MIN30, 30},
{KQuery::MIN60, 60},
{KQuery::HOUR2, 60 * 2},
{KQuery::HOUR4, 60 * 4},
{KQuery::HOUR6, 60 * 6},
{KQuery::HOUR12, 60 * 12},
{KQuery::DAY, 60 * 24},
{KQuery::WEEK, 60 * 24 * 7},
{KQuery::MONTH, 60 * 24 * 30},
{KQuery::QUARTER, 60 * 24 * 30 * 3},
{KQuery::HALFYEAR, 60 * 24 * 30 * 6},
{KQuery::YEAR, 60 * 24 * 365},
{KQuery::DAY, 60 * 24},
{KQuery::WEEK, 60 * 24 * 7},
{KQuery::MONTH, 60 * 24 * 30},
{KQuery::QUARTER, 60 * 24 * 30 * 3},
{KQuery::HALFYEAR, 60 * 24 * 30 * 6},
{KQuery::YEAR, 60 * 24 * 365},
};
// 获取所有的 KType
@ -163,4 +163,16 @@ HKU_API std::ostream& operator<<(std::ostream& os, const KQuery& query) {
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

View File

@ -244,18 +244,8 @@ HKU_API std::ostream& operator<<(std::ostream& os, const KQuery& query);
// 关系比较函数, 不直接在类中定义是为了支持 Null<>() == dNull可以放在左边
//
///////////////////////////////////////////////////////////////////////////////
bool operator==(const KQuery&, const KQuery&);
bool 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);
}
bool HKU_API operator==(const KQuery&, const KQuery&);
bool HKU_API operator!=(const KQuery&, const KQuery&);
/**
* 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));
}
bool HKU_API operator!=(const KRecord& d1, const KRecord& d2) {
return !(d1 == d2);
}
} // 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);
/**
* KRecord不等比较
* @ingroup StockManage
*/
bool HKU_API operator!=(const KRecord& d1, const KRecord& d2);
} // namespace hku
#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,
precision, minTradeNumber, maxTradeNumber)) {}
bool Stock::operator!=(const Stock& stock) const {
HKU_IF_RETURN(this == &stock, false);
HKU_IF_RETURN(m_data == stock.m_data, false);
HKU_IF_RETURN(!m_data || !stock.m_data, true);
HKU_IF_RETURN(m_data->m_code != stock.code() || m_data->m_market != stock.market(), true);
return false;
bool Stock::operator==(const Stock& stock) const {
return this == &stock || m_data == stock.m_data ||
(m_data && stock.m_data && (m_data->m_code == stock.m_data->m_code) &&
(m_data->m_market == stock.m_data->m_market));
}
const string& Stock::market() const {

View File

@ -233,14 +233,14 @@ private:
};
struct HKU_API Stock::Data {
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; // 证券最后日期
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; // 证券最后日期
StockWeightList m_weightList; // 权息信息列表
std::mutex m_weight_mutex;
@ -291,8 +291,8 @@ inline uint64_t Stock::id() const {
return isNull() ? 0 : (int64_t)m_data.get();
}
inline bool Stock::operator==(const Stock& stock) const {
return (*this != stock) ? false : true;
inline bool Stock::operator!=(const Stock& stock) const {
return !(*this == stock);
}
} // namespace hku

View File

@ -20,6 +20,88 @@ namespace hku {
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() {
auto cpu_num = std::thread::hardware_concurrency();
if (cpu_num > 32) {
@ -501,6 +583,10 @@ void IndicatorImp::add(OPType op, IndicatorImpPtr left, IndicatorImpPtr right) {
m_three->m_parent = this;
}
if (m_name == "IndicatorImp") {
m_name = getOPTypeName(op);
}
repeatALikeNodes();
}
@ -514,6 +600,9 @@ void IndicatorImp::add_if(IndicatorImpPtr cond, IndicatorImpPtr left, IndicatorI
m_three->m_parent = this;
m_left->m_parent = this;
m_right->m_parent = this;
if (m_name == "IndicatorImp") {
m_name = getOPTypeName(IndicatorImp::OP_IF);
}
repeatALikeNodes();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,12 +16,12 @@
namespace hku {
// 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();
return 1;
}
SQLiteConnect::SQLiteConnect(const Parameter& param) : DBConnectBase(param), m_db(nullptr) {
SQLiteConnect::SQLiteConnect(const Parameter &param) : DBConnectBase(param), m_db(nullptr) {
try {
m_dbname = getParam<string>("db");
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);
}
} catch (std::out_of_range& e) {
} catch (std::out_of_range &e) {
HKU_FATAL("Can't get database name! {}", e.what());
close();
throw;
} catch (SQLException& e) {
} catch (SQLException &e) {
HKU_FATAL("Failed open database: {})! SQLite3 errcode: {}, errmsg: {}", m_dbname,
e.errcode(), e.what());
close();
throw;
} catch (std::exception& e) {
} catch (std::exception &e) {
HKU_FATAL("Failed initialize data driver({})! exception: {}", m_dbname, e.what());
close();
throw;
@ -108,15 +108,21 @@ void SQLiteConnect::commit() {
exec("COMMIT TRANSACTION");
}
void SQLiteConnect::rollback() {
exec("ROLLBACK TRANSACTION");
void SQLiteConnect::rollback() noexcept {
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) {
return std::make_shared<SQLiteStatement>(this, sql_statement);
}
bool SQLiteConnect::tableExist(const string& tablename) {
bool SQLiteConnect::tableExist(const string &tablename) {
SQLStatementPtr st =
getStatement(fmt::format("select count(1) from sqlite_master where name='{}'", tablename));
st->exec();

View File

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

View File

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

View File

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

View File

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

View File

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