From 729809b16bc2fd1d4d8a4368417ac91e2bd813e2 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 13:33:26 +0800 Subject: [PATCH 1/7] fixed IDma result_num --- hikyuu_cpp/hikyuu/indicator/imp/IDma.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hikyuu_cpp/hikyuu/indicator/imp/IDma.cpp b/hikyuu_cpp/hikyuu/indicator/imp/IDma.cpp index df76ba11a..29ac67277 100644 --- a/hikyuu_cpp/hikyuu/indicator/imp/IDma.cpp +++ b/hikyuu_cpp/hikyuu/indicator/imp/IDma.cpp @@ -38,7 +38,7 @@ void IDma::_calculate(const Indicator& ind) { size_t total = ind.size(); HKU_IF_RETURN(total == 0, void()); - _readyBuffer(total, 2); + _readyBuffer(total, 1); auto k = getContext(); m_ref_ind.setContext(k); From bad9edb1d89ab48515d8ed2934a1f2492d6aadfd Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 16:27:46 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E4=BC=98=E5=8C=96=20INDEXC/INDEXO=20?= =?UTF-8?q?=E7=AD=89=E4=B8=BA=E5=AF=B9=E5=BA=94=E5=A4=A7=E7=9B=98=E6=8C=87?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hikyuu_cpp/hikyuu/indicator/crt/INDEX.cpp | 62 +------- hikyuu_cpp/hikyuu/indicator/crt/INDEX.h | 58 +++++--- hikyuu_cpp/hikyuu/indicator/imp/IIndex.cpp | 135 ++++++++++++++++++ hikyuu_cpp/hikyuu/indicator/imp/IIndex.h | 26 ++++ .../unit_test/hikyuu/indicator/test_INDEX.cpp | 114 +++++++++++++++ hikyuu_pywrap/indicator/_build_in.cpp | 42 +++--- 6 files changed, 335 insertions(+), 102 deletions(-) create mode 100644 hikyuu_cpp/hikyuu/indicator/imp/IIndex.cpp create mode 100644 hikyuu_cpp/hikyuu/indicator/imp/IIndex.h create mode 100644 hikyuu_cpp/unit_test/hikyuu/indicator/test_INDEX.cpp diff --git a/hikyuu_cpp/hikyuu/indicator/crt/INDEX.cpp b/hikyuu_cpp/hikyuu/indicator/crt/INDEX.cpp index 1429da4fc..88d3ae678 100644 --- a/hikyuu_cpp/hikyuu/indicator/crt/INDEX.cpp +++ b/hikyuu_cpp/hikyuu/indicator/crt/INDEX.cpp @@ -10,66 +10,6 @@ namespace hku { -Indicator HKU_API INDEXO() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.open()); -} - -Indicator HKU_API INDEXO(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.open()); -} - -Indicator HKU_API INDEXH() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.high()); -} - -Indicator HKU_API INDEXH(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.high()); -} - -Indicator HKU_API INDEXL() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.low()); -} - -Indicator HKU_API INDEXL(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.low()); -} - -Indicator HKU_API INDEXC() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.close()); -} - -Indicator HKU_API INDEXC(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.close()); -} - -Indicator HKU_API INDEXA() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.amo()); -} - -Indicator HKU_API INDEXA(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.amo()); -} - -Indicator HKU_API INDEXV() { - KData k = getKData("SH000001", KQueryByIndex(-1)); - return CONTEXT(k.vol()); -} - -Indicator HKU_API INDEXV(const KQuery& query) { - KData k = getKData("SH000001", query); - return CONTEXT(k.vol()); -} - Indicator HKU_API INDEXADV() { KData k = getKData("SH880005", KQueryByIndex(-1)); return CONTEXT(k.close()); @@ -90,4 +30,4 @@ Indicator HKU_API INDEXDEC(const KQuery& query) { return CONTEXT(k.open()); } -} \ No newline at end of file +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/indicator/crt/INDEX.h b/hikyuu_cpp/hikyuu/indicator/crt/INDEX.h index 2465b17a2..3df3220e6 100644 --- a/hikyuu_cpp/hikyuu/indicator/crt/INDEX.h +++ b/hikyuu_cpp/hikyuu/indicator/crt/INDEX.h @@ -13,29 +13,41 @@ namespace hku { // 这里的大盘都指 sh000001 -/** 大盘开盘价 */ -Indicator HKU_API INDEXO(); -Indicator HKU_API INDEXO(const KQuery& query); - -/** 大盘最高价盘价 */ -Indicator HKU_API INDEXH(); -Indicator HKU_API INDEXH(const KQuery& query); - -/** 大盘最低价 */ -Indicator HKU_API INDEXL(); -Indicator HKU_API INDEXL(const KQuery& query); - -/** 大盘收盘价 */ -Indicator HKU_API INDEXC(); -Indicator HKU_API INDEXC(const KQuery& query); - -/** 大盘成交额 */ -Indicator HKU_API INDEXA(); -Indicator HKU_API INDEXA(const KQuery& query); - -/** 大盘成交量 */ -Indicator HKU_API INDEXV(); -Indicator HKU_API INDEXV(const KQuery& query); +/** 对应的大盘开盘价,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXO(bool fill_null = true); +inline Indicator INDEXO(const KData& k, bool fill_null = true) { + return INDEXO(fill_null)(k); +} + +/** 对应的大盘最高价,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXH(bool fill_null = true); +inline Indicator INDEXH(const KData& k, bool fill_null = true) { + return INDEXH(fill_null)(k); +} + +/** 对应的大盘最低价,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXL(bool fill_null = true); +inline Indicator INDEXL(const KData& k, bool fill_null = true) { + return INDEXL(fill_null)(k); +} + +/** 对应的大盘收盘价,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXC(bool fill_null = true); +inline Indicator INDEXC(const KData& k, bool fill_null = true) { + return INDEXC(fill_null)(k); +} + +/** 对应的大盘成交金额,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXA(bool fill_null = true); +inline Indicator INDEXA(const KData& k, bool fill_null = true) { + return INDEXA(fill_null)(k); +} + +/** 对应的大盘成交量,分别是上证指数,深证成指,科创50,创业板指 */ +Indicator HKU_API INDEXV(bool fill_null = true); +inline Indicator INDEXV(const KData& k, bool fill_null = true) { + return INDEXV(fill_null)(k); +} /** 大盘上涨家数, 使用通达信 SH880005,可能无法用于实盘 */ Indicator HKU_API INDEXADV(); diff --git a/hikyuu_cpp/hikyuu/indicator/imp/IIndex.cpp b/hikyuu_cpp/hikyuu/indicator/imp/IIndex.cpp new file mode 100644 index 000000000..0a99ea732 --- /dev/null +++ b/hikyuu_cpp/hikyuu/indicator/imp/IIndex.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2024 hikyuu.org + * + * Created on: 2024-03-10 + * Author: fasiondog + */ + +#include "hikyuu/StockTypeInfo.h" +#include "hikyuu/indicator/crt/KDATA.h" +#include "hikyuu/indicator/crt/ALIGN.h" +#include "hikyuu/indicator/crt/CVAL.h" +#include "hikyuu/indicator/crt/SLICE.h" +#include "IIndex.h" + +#if HKU_SUPPORT_SERIALIZATION +BOOST_CLASS_EXPORT(hku::IIndex) +#endif + +namespace hku { + +IIndex::IIndex() : IndicatorImp("INDEX", 1) { + setParam("fill_null", true); + setParam("kpart", "CLOSE"); + setParam("market_code", "SH000001"); +} + +IIndex::IIndex(const string& kpart, bool fill_null) : IndicatorImp("INDEX", 1) { + setParam("fill_null", fill_null); + string part_name(kpart); + to_upper(part_name); + setParam("kpart", part_name); + setParam("market_code", "SH000001"); +} + +IIndex::~IIndex() {} + +void IIndex::_checkParam(const string& name) const { + if ("kpart" == name) { + string part = getParam("kpart"); + HKU_ASSERT("OPEN" == part || "HIGH" == part || "LOW" == part || "CLOSE" == part || + "AMO" == part || "VOL" == part); + } +} + +void IIndex::_calculate(const Indicator& ind) { + auto k = getContext(); + size_t total = k.size(); + HKU_IF_RETURN(total == 0, void()); + + _readyBuffer(total, 1); + + string market_code = getParam("market_code"); + Stock stk = k.getStock(); + if (stk.type() == STOCKTYPE_A) { + if (stk.market() == "SH") { + market_code = "SH000001"; + } else if (stk.market() == "SZ") { + market_code = "SZ399001"; + } else { + HKU_WARN("Not known the index code, will use SH000001 as default."); + } + } else if (stk.type() == STOCKTYPE_A_BJ) { + market_code = "BJ899050"; + } else if (stk.type() == STOCKTYPE_START) { + market_code = "SH000688"; + } else if (stk.type() == STOCKTYPE_GEM) { + market_code = "SZ399006"; + } else { + HKU_WARN("Not known the index code, will use {} as default.", market_code); + } + + // 调整 market_code 参数为当前指数 market_code + setParam("market_code", market_code); + + KQuery query = k.getQuery(); + auto minutes = KQuery::getKTypeInMin(query.kType()); + query = KQueryByDate(k[0].datetime, k[total - 1].datetime + Minutes(minutes), query.kType(), + query.recoverType()); + + KData index_k = getKData(market_code, query); + HKU_ASSERT(index_k.size() == total); + Indicator index = + ALIGN(KDATA_PART(index_k, getParam("kpart")), k, getParam("fill_null")); + + HKU_ASSERT(index.size() == total); + const auto* src = index.data(); + auto* dst = this->data(); + for (size_t i = 0; i < total; i++) { + dst[i] = src[i]; + } +} + +static Indicator INDEX(const string& kpart, bool fill_null) { + IndicatorImpPtr p = make_shared(kpart, fill_null); + if ("OPEN" == kpart) { + p->name("INDEXO"); + } else if ("HIGH" == kpart) { + p->name("INDEXH"); + } else if ("LOW" == kpart) { + p->name("INDEXL"); + } else if ("CLOSE" == kpart) { + p->name("INDEXC"); + } else if ("AMO" == kpart) { + p->name("INDEXA"); + } else if ("VOL" == kpart) { + p->name("INDEXV"); + } + return p->calculate(); +} + +Indicator HKU_API INDEXO(bool fill_null) { + return INDEX("OPEN", fill_null); +} + +Indicator HKU_API INDEXH(bool fill_null) { + return INDEX("HIGH", fill_null); +} + +Indicator HKU_API INDEXL(bool fill_null) { + return INDEX("LOW", fill_null); +} + +Indicator HKU_API INDEXC(bool fill_null) { + return INDEX("CLOSE", fill_null); +} + +Indicator HKU_API INDEXA(bool fill_null) { + return INDEX("AMO", fill_null); +} + +Indicator HKU_API INDEXV(bool fill_null) { + return INDEX("VOL", fill_null); +} + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/indicator/imp/IIndex.h b/hikyuu_cpp/hikyuu/indicator/imp/IIndex.h new file mode 100644 index 000000000..6a4799589 --- /dev/null +++ b/hikyuu_cpp/hikyuu/indicator/imp/IIndex.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 hikyuu.org + * + * Created on: 2024-09-09 + * Author: fasiondog + */ + +#pragma once + +#include "../Indicator.h" + +namespace hku { + +class IIndex : public IndicatorImp { + INDICATOR_IMP(IIndex) + INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION + +public: + IIndex(); + IIndex(const string& kpart, bool fill_null); + virtual ~IIndex(); + + virtual void _checkParam(const string& name) const override; +}; + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/unit_test/hikyuu/indicator/test_INDEX.cpp b/hikyuu_cpp/unit_test/hikyuu/indicator/test_INDEX.cpp new file mode 100644 index 000000000..849b6d282 --- /dev/null +++ b/hikyuu_cpp/unit_test/hikyuu/indicator/test_INDEX.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025 hikyuu.org + * + * Created on: 2025-01-26 + * Author: fasiondog + */ + +#include "doctest/doctest.h" +#include +#include +#include +#include +#include + +using namespace hku; + +/** + * @defgroup test_indicator_INDEX test_indicator_INDEX + * @ingroup test_hikyuu_indicator_suite + * @{ + */ + +/** @par 检测点 */ +TEST_CASE("test_INDEXO") { + /** @arg 空指标 */ + Indicator result = INDEXO(); + CHECK_UNARY(result.empty()); + CHECK_EQ(result.name(), "INDEXO"); + + /** @arg 上证日线 */ + KQuery query = KQueryByDate(Datetime(20111130), Datetime(20111206)); + auto k = getKData("sh600004", query); + REQUIRE(k.size() > 0); + result = INDEXO(k); + CHECK_EQ(result.name(), "INDEXO"); + CHECK_EQ(result.size(), k.size()); + + auto expect_k = getKData("sh000001", query); + Indicator expect = OPEN(expect_k); + for (size_t i = 0, total = result.size(); i < total; ++i) { + CHECK_EQ(result[i], expect[i]); + } + + /** @arg 上证5分钟线 */ + query = KQueryByDate(Datetime(201111300930), Datetime(201111301400), KQuery::MIN5); + k = getKData("sh600004", query); + REQUIRE(k.size() > 0); + result = INDEXO(k); + CHECK_EQ(result.name(), "INDEXO"); + CHECK_EQ(result.size(), k.size()); + + expect_k = getKData("sh000001", query); + expect = OPEN(expect_k); + for (size_t i = 0, total = result.size(); i < total; ++i) { + CHECK_EQ(result[i], expect[i]); + } + + /** @arg 上证周线 */ + query = KQueryByDate(Datetime(20111101), Datetime(20111201), KQuery::WEEK); + k = getKData("sh600004", query); + REQUIRE(k.size() > 0); + result = INDEXO(k); + CHECK_EQ(result.name(), "INDEXO"); + CHECK_EQ(result.size(), k.size()); + + expect_k = getKData("sh000001", query); + expect = OPEN(expect_k); + for (size_t i = 0, total = result.size(); i < total; ++i) { + CHECK_EQ(result[i], expect[i]); + } +} + +//----------------------------------------------------------------------------- +// test export +//----------------------------------------------------------------------------- +#if HKU_SUPPORT_SERIALIZATION + +/** @par 检测点 */ +TEST_CASE("test_INDEX_export") { + StockManager& sm = StockManager::instance(); + string filename(sm.tmpdir()); + filename += "/INDEX.xml"; + + Stock stock = sm.getStock("sh000001"); + KData kdata = stock.getKData(KQuery(-5)); + Indicator x1 = INDEXC(kdata); + { + std::ofstream ofs(filename); + boost::archive::xml_oarchive oa(ofs); + oa << BOOST_SERIALIZATION_NVP(x1); + } + + Indicator x2; + { + std::ifstream ifs(filename); + boost::archive::xml_iarchive ia(ifs); + ia >> BOOST_SERIALIZATION_NVP(x2); + } + + CHECK_EQ(x1.name(), x2.name()); + CHECK_EQ(x1.size(), x2.size()); + CHECK_EQ(x1.discard(), x2.discard()); + CHECK_EQ(x1.getResultNumber(), x2.getResultNumber()); + for (size_t i = x1.discard(); i < x1.size(); ++i) { + if (std::isinf(x1[i])) { + CHECK_UNARY(std::isinf(x2[i])); + } else { + CHECK_EQ(x1[i], doctest::Approx(x2[i])); + } + } +} +#endif /* #if HKU_SUPPORT_SERIALIZATION */ + +/** @} */ diff --git a/hikyuu_pywrap/indicator/_build_in.cpp b/hikyuu_pywrap/indicator/_build_in.cpp index 4d6aea4ae..d008fbe28 100644 --- a/hikyuu_pywrap/indicator/_build_in.cpp +++ b/hikyuu_pywrap/indicator/_build_in.cpp @@ -2042,35 +2042,41 @@ void export_Indicator_build_in(py::module& m) { :param bool ignore_discard: 忽略指标丢弃数据 :rtype: Indicator)"); - m.def("INDEXO", py::overload_cast<>(INDEXO)); - m.def("INDEXO", py::overload_cast(INDEXO), R"(INDEXO([query]) + m.def("INDEXO", py::overload_cast(INDEXO), py::arg("fill_null") = true); + m.def("INDEXO", py::overload_cast(INDEXO), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXO([query]) - 大盘开盘价)"); + 返回对应的大盘开盘价,分别是上证指数,深证成指,科创50,创业板指)"); - m.def("INDEXH", py::overload_cast<>(INDEXH)); - m.def("INDEXH", py::overload_cast(INDEXH), R"(INDEXH([query]) + m.def("INDEXH", py::overload_cast(INDEXH), py::arg("fill_null") = true); + m.def("INDEXH", py::overload_cast(INDEXH), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXH([query]) - 大盘最高价)"); + 返回对应的大盘最高价,分别是上证指数,深证成指,科创50,创业板指)"); - m.def("INDEXL", py::overload_cast<>(INDEXL)); - m.def("INDEXL", py::overload_cast(INDEXL), R"(INDEXL([query]) + m.def("INDEXL", py::overload_cast(INDEXL), py::arg("fill_null") = true); + m.def("INDEXL", py::overload_cast(INDEXL), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXL([query]) - 大盘最低价)"); + 返回对应的大盘最低价,分别是上证指数,深证成指,科创50,创业板指)"); - m.def("INDEXC", py::overload_cast<>(INDEXC)); - m.def("INDEXC", py::overload_cast(INDEXC), R"(INDEXC([query]) + m.def("INDEXC", py::overload_cast(INDEXC), py::arg("fill_null") = true); + m.def("INDEXC", py::overload_cast(INDEXC), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXC([query]) - 大盘收盘价)"); + 返回对应的大盘收盘价,分别是上证指数,深证成指,科创50,创业板指)"); - m.def("INDEXV", py::overload_cast<>(INDEXV)); - m.def("INDEXV", py::overload_cast(INDEXV), R"(INDEXV([query]) + m.def("INDEXV", py::overload_cast(INDEXV), py::arg("fill_null") = true); + m.def("INDEXV", py::overload_cast(INDEXV), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXV([query]) - 大盘成交量)"); + 返回对应的大盘成交量,分别是上证指数,深证成指,科创50,创业板指)"); - m.def("INDEXA", py::overload_cast<>(INDEXA)); - m.def("INDEXA", py::overload_cast(INDEXA), R"(INDEXA([query]) + m.def("INDEXA", py::overload_cast(INDEXA), py::arg("fill_null") = true); + m.def("INDEXA", py::overload_cast(INDEXA), py::arg("kdata"), + py::arg("fill_null") = true, R"(INDEXA([query]) - 大盘成交额)"); + 返回对应的大盘成交金额,分别是上证指数,深证成指,科创50,创业板指)"); m.def("INDEXADV", py::overload_cast<>(INDEXADV)); m.def("INDEXADV", py::overload_cast(INDEXADV), R"(INDEXADV([query]) From 68eca2c056b4a5958f3771aa9e8ef71e51c27a05 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 17:35:48 +0800 Subject: [PATCH 3/7] add INBLOCK indicator --- hikyuu_cpp/hikyuu/indicator/build_in.h | 1 + hikyuu_cpp/hikyuu/indicator/crt/INBLOCK.h | 31 ++++++++++ hikyuu_cpp/hikyuu/indicator/imp/IInBlock.cpp | 59 ++++++++++++++++++++ hikyuu_cpp/hikyuu/indicator/imp/IInBlock.h | 30 ++++++++++ hikyuu_cpp/unit_test/xmake.lua | 7 +-- hikyuu_pywrap/indicator/_build_in.cpp | 5 ++ 6 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 hikyuu_cpp/hikyuu/indicator/crt/INBLOCK.h create mode 100644 hikyuu_cpp/hikyuu/indicator/imp/IInBlock.cpp create mode 100644 hikyuu_cpp/hikyuu/indicator/imp/IInBlock.h diff --git a/hikyuu_cpp/hikyuu/indicator/build_in.h b/hikyuu_cpp/hikyuu/indicator/build_in.h index cf3205259..7f0b25b70 100644 --- a/hikyuu_cpp/hikyuu/indicator/build_in.h +++ b/hikyuu_cpp/hikyuu/indicator/build_in.h @@ -53,6 +53,7 @@ #include "crt/HSL.h" #include "crt/IC.h" #include "crt/ICIR.h" +#include "crt/INBLOCK.h" #include "crt/INDEX.h" #include "crt/INSUM.h" #include "crt/IR.h" diff --git a/hikyuu_cpp/hikyuu/indicator/crt/INBLOCK.h b/hikyuu_cpp/hikyuu/indicator/crt/INBLOCK.h new file mode 100644 index 000000000..0172b321b --- /dev/null +++ b/hikyuu_cpp/hikyuu/indicator/crt/INBLOCK.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 hikyuu.org + * + * Created on: 2025-01-26 + * Author: fasiondog + */ + +#pragma once + +#include "../Indicator.h" + +namespace hku { + +/** + * @brief 返回品种是否属于某板块 + * @param category 指定板块分类 + * @param name 板块名称 + * @return Indicator + */ +Indicator HKU_API INBLOCK(const string& category, const string& name); + +/** + * @brief 返回品种是否属于某板块 + * @param kdata K线数据 + * @param category 指定板块分类 + * @param name 板块名称 + * @return Indicator + */ +Indicator HKU_API INBLOCK(const KData& kdata, const string& category, const string& name); + +} // namespace hku \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.cpp b/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.cpp new file mode 100644 index 000000000..422645d9a --- /dev/null +++ b/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 hikyuu.org + * + * Created on: 2025-01-26 + * Author: fasiondog + */ + +#include "IInBlock.h" + +#if HKU_SUPPORT_SERIALIZATION +BOOST_CLASS_EXPORT(hku::IInBlock) +#endif + +namespace hku { + +IInBlock::IInBlock() : IndicatorImp("INBLOCK", 1) { + setParam("category", ""); + setParam("name", ""); +} + +IInBlock::~IInBlock() {} + +IInBlock::IInBlock(const KData& kdata, const string& category, const string& name) +: IndicatorImp("INBLOCK", 1) { + setParam("category", category); + setParam("name", name); + setParam("kdata", kdata); + IInBlock::_calculate(Indicator()); +} + +void IInBlock::_calculate(const Indicator& data) { + HKU_IF_RETURN(!isLeaf() && !data.empty(), void()); + + KData k = getContext(); + size_t total = k.size(); + HKU_IF_RETURN(total == 0, void()); + + _readyBuffer(total, 1); + + Block block = getBlock(getParam("category"), getParam("name")); + value_t in = block.have(k.getStock()) ? 1.0 : 0.0; + auto* dst = this->data(); + for (size_t i = 0; i < total; ++i) { + dst[i] = in; + } +} + +Indicator HKU_API INBLOCK(const string& category, const string& name) { + auto p = make_shared(); + p->setParam("category", category); + p->setParam("name", name); + return Indicator(p); +} + +Indicator HKU_API INBLOCK(const KData& k, const string& category, const string& name) { + return Indicator(make_shared(k, category, name)); +} + +} /* namespace hku */ diff --git a/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.h b/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.h new file mode 100644 index 000000000..54f015deb --- /dev/null +++ b/hikyuu_cpp/hikyuu/indicator/imp/IInBlock.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 hikyuu.org + * + * Created on: 2025-01-26 + * Author: fasiondog + */ + +#pragma once +#ifndef INDICATOR_IMP_IINBLOCK_H_ +#define INDICATOR_IMP_IINBLOCK_H_ + +#include "../Indicator.h" + +namespace hku { + +/* 已指标形式返回是否在指定板块中 */ +class IInBlock : public IndicatorImp { + INDICATOR_IMP(IInBlock) + INDICATOR_NEED_CONTEXT + INDICATOR_IMP_NO_PRIVATE_MEMBER_SERIALIZATION + +public: + IInBlock(); + explicit IInBlock(const KData& kdata, const string& category, const string& name); + virtual ~IInBlock(); +}; + +} /* namespace hku */ + +#endif /* INDICATOR_IMP_IINBLOCK_H_ */ diff --git a/hikyuu_cpp/unit_test/xmake.lua b/hikyuu_cpp/unit_test/xmake.lua index 79f8acd21..4f98c03bd 100644 --- a/hikyuu_cpp/unit_test/xmake.lua +++ b/hikyuu_cpp/unit_test/xmake.lua @@ -165,7 +165,7 @@ target("real-test") set_kind("binary") set_default(false) - add_packages("boost", "fmt", "spdlog", "doctest", "sqlite3") + add_packages("boost", "fmt", "spdlog", "doctest", "sqlite3", "mysql") if get_config("mysql") then if is_plat("macosx") then add_packages("mysqlclient") @@ -196,11 +196,6 @@ target("real-test") add_shflags("-Wl,-rpath=$ORIGIN", "-Wl,-rpath=$ORIGIN/../lib") end - if is_plat("macosx") then - add_includedirs("/usr/local/opt/mysql-client/include") - add_linkdirs("/usr/local/opt/mysql-client/lib") - end - -- add files add_files("./hikyuu/real_data/**.cpp"); add_files("./hikyuu/test_main.cpp") diff --git a/hikyuu_pywrap/indicator/_build_in.cpp b/hikyuu_pywrap/indicator/_build_in.cpp index d008fbe28..7333472ad 100644 --- a/hikyuu_pywrap/indicator/_build_in.cpp +++ b/hikyuu_pywrap/indicator/_build_in.cpp @@ -2096,4 +2096,9 @@ void export_Indicator_build_in(py::module& m) { 用法: WINNER(CLOSE) 表示以当前收市价卖出的获利盘比例。 例如: 返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例 该函数仅对日线分析周期有效,且仅对存在流通盘权息数据的证券有效,对指数、基金等无效。)"); + + m.def("INBLOCK", py::overload_cast(INBLOCK), py::arg("category"), + py::arg("name")); + m.def("INBLOCK", py::overload_cast(INBLOCK), + py::arg("data"), py::arg("category"), py::arg("name")); } From 8fdb2b327b79d1e9637e7b11aebb741be7c77819 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 18:13:53 +0800 Subject: [PATCH 4/7] =?UTF-8?q?MySQL=E9=A9=B1=E5=8A=A8=E9=87=8D=E8=BF=9E?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=81=A2=E5=A4=8D=E9=87=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utilities/db_connect/mysql/MySQLConnect.h | 6 +-- .../db_connect/mysql/MySQLStatement.cpp | 42 ++++++++----------- .../db_connect/mysql/MySQLStatement.h | 2 +- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h index 269a40e5a..60c2a619d 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h @@ -41,17 +41,13 @@ class HKU_UTILS_API MySQLConnect : public DBConnectBase { virtual void commit() override; virtual void rollback() noexcept override; -public: - MYSQL *getRawMYSQL() const noexcept { - return m_mysql; - } - private: bool tryConnect() noexcept; void connect(); void close(); private: + friend class MySQLStatement; MYSQL *m_mysql; }; diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp index 610709940..f15a127cf 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp @@ -25,19 +25,12 @@ namespace hku { MySQLStatement::MySQLStatement(DBConnectBase* driver, const std::string& sql_statement) : SQLStatementBase(driver, sql_statement), + m_db((dynamic_cast(driver))->m_mysql), m_stmt(nullptr), m_meta_result(nullptr), m_needs_reset(false), m_has_bind_result(false) { - MySQLConnect* connect = dynamic_cast(driver); - if (!connect) { - HKU_ERROR("Failed create statement: {}! Failed dynamic_cast!", - sql_statement); - return; - } - - m_db = connect->getRawMYSQL(); - HKU_CHECK(_prepare(driver), "Failed prepare statement: {}!", sql_statement); + _prepare(driver); auto param_count = mysql_stmt_param_count(m_stmt); if (param_count > 0) { @@ -63,37 +56,36 @@ MySQLStatement::~MySQLStatement() { mysql_stmt_close(m_stmt); } -bool MySQLStatement::_prepare(DBConnectBase* driver) noexcept { +void MySQLStatement::_prepare(DBConnectBase* driver) { m_stmt = mysql_stmt_init(m_db); - HKU_ERROR_IF_RETURN(!m_stmt, false, "Failed mysql_stmt_init!"); + HKU_CHECK(m_stmt, "Failed mysql_stmt_init!"); int ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, true); + HKU_IF_RETURN(0 == ret, void()); mysql_stmt_close(m_stmt); m_stmt = nullptr; - HKU_ERROR_IF_RETURN(CR_OUT_OF_MEMORY == ret, false, "Out of memory!"); - - // 非内存不足错误时,都尝试重连 - HKU_WARN("Will tryrReconnect, because failed prepare statement: {}! ret: {}, error msg: {}!", - m_sql_string, ret, mysql_stmt_error(m_stmt)); - MySQLConnect* connect = dynamic_cast(driver); - HKU_ERROR_IF_RETURN(!connect || !connect->ping(), false, "Failed reconnect mysql!"); - - m_db = connect->getRawMYSQL(); - HKU_ERROR_IF_RETURN(!m_db, false, "Got a empty MYSQL* m_db!"); + // 如果是服务器异常,尝试重连服务器 + if (CR_SERVER_LOST == ret || CR_SERVER_GONE_ERROR == ret) { + if ((dynamic_cast(driver))->ping()) { + m_db = (dynamic_cast(driver))->m_mysql; + } else { + HKU_THROW("Failed reconnect mysql!"); + } + } else if (CR_OUT_OF_MEMORY == ret) { + HKU_THROW("Out of memory!"); + } m_stmt = mysql_stmt_init(m_db); ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, true); + HKU_IF_RETURN(0 == ret, void()); std::string stmt_errorstr(mysql_stmt_error(m_stmt)); mysql_stmt_close(m_stmt); m_stmt = nullptr; - HKU_ERROR("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, + HKU_THROW("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, stmt_errorstr); - return false; } void MySQLStatement::_reset() { diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h index fbb550b1c..80eb0e344 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h @@ -60,7 +60,7 @@ class HKU_UTILS_API MySQLStatement : public SQLStatementBase { virtual void sub_getColumnAsBlob(int idx, std::vector &item) override; private: - bool _prepare(DBConnectBase *driver) noexcept; + void _prepare(DBConnectBase *driver); void _reset(); void _bindResult(); From 1cabbef95861a69a984299d2658f7d28b6364bef Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 22:36:27 +0800 Subject: [PATCH 5/7] update --- hikyuu/data/em_block_to_mysql.py | 3 ++- hikyuu/data/em_block_to_sqlite.py | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hikyuu/data/em_block_to_mysql.py b/hikyuu/data/em_block_to_mysql.py index 6cbfdeb95..3a3c3c467 100644 --- a/hikyuu/data/em_block_to_mysql.py +++ b/hikyuu/data/em_block_to_mysql.py @@ -74,7 +74,7 @@ def em_import_block_to_mysql(connect, code_market_dict, categorys=('行业板块 hku_info("更新数据库") cur = connect.cursor() if len(blks) == 1: - sql = f"delete from hku_base.block where category in ({blks[0]})" + sql = f"delete from hku_base.block where category in ('{blks[0]}')" else: sql = f"delete from hku_base.block where category in {tuple(blks)}" cur.execute(sql) @@ -88,6 +88,7 @@ def em_import_block_to_mysql(connect, code_market_dict, categorys=('行业板块 if insert_records: sql = "insert into hku_base.block (category, name, market_code) values (%s,%s,%s)" + hku_info(f"insert block records: {len(insert_records)}") cur.executemany(sql, insert_records) connect.commit() diff --git a/hikyuu/data/em_block_to_sqlite.py b/hikyuu/data/em_block_to_sqlite.py index 571a16ad8..cf5c99586 100644 --- a/hikyuu/data/em_block_to_sqlite.py +++ b/hikyuu/data/em_block_to_sqlite.py @@ -75,7 +75,7 @@ def em_import_block_to_sqlite(connect, code_market_dict, categorys=('行业板 hku_info("更新数据库") cur = connect.cursor() if len(blks) == 1: - sql = f"delete from block where category in ({blks[0]})" + sql = f"delete from block where category in ('{blks[0]}')" else: sql = f"delete from block where category in {tuple(blks)}" hku_info(sql) @@ -90,6 +90,7 @@ def em_import_block_to_sqlite(connect, code_market_dict, categorys=('行业板 if insert_records: sql = "insert into block (category, name, market_code) values (?,?,?)" + hku_info(f"insert block records: {len(insert_records)}") cur.executemany(sql, insert_records) connect.commit() @@ -101,7 +102,8 @@ def em_import_block_to_sqlite(connect, code_market_dict, categorys=('行业板 from hikyuu.data.common_sqlite3 import create_database # dest_dir = "/home/fasiondog/stock" - dest_dir = "d:\\stock" + dest_dir = "/Users/fasiondog/stock" + # dest_dir = "d:\\stock" connect = sqlite3.connect(dest_dir + "/stock.db") create_database(connect) @@ -112,6 +114,6 @@ def em_import_block_to_sqlite(connect, code_market_dict, categorys=('行业板 code_market_dict[v["code"]] = MARKET.SH # print(code_market_dict) - em_import_block_to_sqlite(connect, code_market_dict) + em_import_block_to_sqlite(connect, code_market_dict, categorys=('行业板块', '指数板块',)) connect.close() From e02cd1e95d21f2b8ade52b542a57a2ad885256ed Mon Sep 17 00:00:00 2001 From: fasiondog Date: Sun, 26 Jan 2025 22:46:27 +0800 Subject: [PATCH 6/7] =?UTF-8?q?MySQL=E9=A9=B1=E5=8A=A8=E9=87=8D=E8=BF=9E?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utilities/db_connect/mysql/MySQLConnect.h | 6 ++- .../db_connect/mysql/MySQLStatement.cpp | 40 +++++++++++-------- .../db_connect/mysql/MySQLStatement.h | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h index 60c2a619d..269a40e5a 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLConnect.h @@ -41,13 +41,17 @@ class HKU_UTILS_API MySQLConnect : public DBConnectBase { virtual void commit() override; virtual void rollback() noexcept override; +public: + MYSQL *getRawMYSQL() const noexcept { + return m_mysql; + } + private: bool tryConnect() noexcept; void connect(); void close(); private: - friend class MySQLStatement; MYSQL *m_mysql; }; diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp index f15a127cf..fe688a70d 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp @@ -25,12 +25,17 @@ namespace hku { MySQLStatement::MySQLStatement(DBConnectBase* driver, const std::string& sql_statement) : SQLStatementBase(driver, sql_statement), - m_db((dynamic_cast(driver))->m_mysql), + m_db(nullptr), m_stmt(nullptr), m_meta_result(nullptr), m_needs_reset(false), m_has_bind_result(false) { - _prepare(driver); + MySQLConnect* connect = dynamic_cast(driver); + HKU_CHECK(connect, "Failed create statement: {}! Failed dynamic_cast!", + sql_statement); + + m_db = connect->getRawMYSQL(); + HKU_CHECK(_prepare(driver), "Failed prepare statement: {}!", sql_statement); auto param_count = mysql_stmt_param_count(m_stmt); if (param_count > 0) { @@ -56,36 +61,37 @@ MySQLStatement::~MySQLStatement() { mysql_stmt_close(m_stmt); } -void MySQLStatement::_prepare(DBConnectBase* driver) { +bool MySQLStatement::_prepare(DBConnectBase* driver) noexcept { m_stmt = mysql_stmt_init(m_db); - HKU_CHECK(m_stmt, "Failed mysql_stmt_init!"); + HKU_ERROR_IF_RETURN(!m_stmt, false, "Failed mysql_stmt_init!"); int ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, void()); + HKU_IF_RETURN(0 == ret, true); mysql_stmt_close(m_stmt); m_stmt = nullptr; - // 如果是服务器异常,尝试重连服务器 - if (CR_SERVER_LOST == ret || CR_SERVER_GONE_ERROR == ret) { - if ((dynamic_cast(driver))->ping()) { - m_db = (dynamic_cast(driver))->m_mysql; - } else { - HKU_THROW("Failed reconnect mysql!"); - } - } else if (CR_OUT_OF_MEMORY == ret) { - HKU_THROW("Out of memory!"); - } + HKU_ERROR_IF_RETURN(CR_OUT_OF_MEMORY == ret, false, "Out of memory!"); + + // 非内存不足错误时,都尝试重连 + HKU_WARN("Will tryrReconnect, because failed prepare statement: {}! ret: {}, error msg: {}!", + m_sql_string, ret, mysql_stmt_error(m_stmt)); + MySQLConnect* connect = dynamic_cast(driver); + HKU_ERROR_IF_RETURN(!connect || !connect->ping(), false, "Failed reconnect mysql!"); + + m_db = connect->getRawMYSQL(); + HKU_ERROR_IF_RETURN(!m_db, false, "Got a empty MYSQL* m_db!"); m_stmt = mysql_stmt_init(m_db); ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, void()); + HKU_IF_RETURN(0 == ret, true); std::string stmt_errorstr(mysql_stmt_error(m_stmt)); mysql_stmt_close(m_stmt); m_stmt = nullptr; - HKU_THROW("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, + HKU_ERROR("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, stmt_errorstr); + return false; } void MySQLStatement::_reset() { diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h index 80eb0e344..fbb550b1c 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h @@ -60,7 +60,7 @@ class HKU_UTILS_API MySQLStatement : public SQLStatementBase { virtual void sub_getColumnAsBlob(int idx, std::vector &item) override; private: - void _prepare(DBConnectBase *driver); + bool _prepare(DBConnectBase *driver) noexcept; void _reset(); void _bindResult(); From 40a8020e57ceef799b8bba200af902a99fee6e4f Mon Sep 17 00:00:00 2001 From: fasiondog Date: Mon, 27 Jan 2025 00:53:55 +0800 Subject: [PATCH 7/7] =?UTF-8?q?MySQL=E9=A9=B1=E5=8A=A8=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db_connect/mysql/MySQLStatement.cpp | 34 +++++++++---------- .../db_connect/mysql/MySQLStatement.h | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp index fe688a70d..8b622da6c 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.cpp @@ -35,7 +35,7 @@ MySQLStatement::MySQLStatement(DBConnectBase* driver, const std::string& sql_sta sql_statement); m_db = connect->getRawMYSQL(); - HKU_CHECK(_prepare(driver), "Failed prepare statement: {}!", sql_statement); + _prepare(driver); auto param_count = mysql_stmt_param_count(m_stmt); if (param_count > 0) { @@ -61,37 +61,37 @@ MySQLStatement::~MySQLStatement() { mysql_stmt_close(m_stmt); } -bool MySQLStatement::_prepare(DBConnectBase* driver) noexcept { +void MySQLStatement::_prepare(DBConnectBase* driver) { m_stmt = mysql_stmt_init(m_db); - HKU_ERROR_IF_RETURN(!m_stmt, false, "Failed mysql_stmt_init!"); + HKU_CHECK(m_stmt, "Failed mysql_stmt_init! SQL: {}", m_sql_string); int ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, true); + HKU_IF_RETURN(0 == ret, void()); mysql_stmt_close(m_stmt); m_stmt = nullptr; - HKU_ERROR_IF_RETURN(CR_OUT_OF_MEMORY == ret, false, "Out of memory!"); - - // 非内存不足错误时,都尝试重连 - HKU_WARN("Will tryrReconnect, because failed prepare statement: {}! ret: {}, error msg: {}!", - m_sql_string, ret, mysql_stmt_error(m_stmt)); - MySQLConnect* connect = dynamic_cast(driver); - HKU_ERROR_IF_RETURN(!connect || !connect->ping(), false, "Failed reconnect mysql!"); - - m_db = connect->getRawMYSQL(); - HKU_ERROR_IF_RETURN(!m_db, false, "Got a empty MYSQL* m_db!"); + // 如果是服务器异常,尝试重连服务器 + if (CR_SERVER_LOST == ret || CR_SERVER_GONE_ERROR == ret) { + MySQLConnect* connect = dynamic_cast(driver); + if (connect && connect->ping()) { + m_db = connect->getRawMYSQL(); + } else { + HKU_THROW("Failed reconnect mysql! SQL: {}", m_sql_string); + } + } else if (CR_OUT_OF_MEMORY == ret) { + HKU_THROW("Out of memory! SQL: {}", m_sql_string); + } m_stmt = mysql_stmt_init(m_db); ret = mysql_stmt_prepare(m_stmt, m_sql_string.c_str(), m_sql_string.size()); - HKU_IF_RETURN(0 == ret, true); + HKU_IF_RETURN(0 == ret, void()); std::string stmt_errorstr(mysql_stmt_error(m_stmt)); mysql_stmt_close(m_stmt); m_stmt = nullptr; - HKU_ERROR("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, + HKU_THROW("Failed prepare statement: {}! ret: {}, error msg: {}!", m_sql_string, ret, stmt_errorstr); - return false; } void MySQLStatement::_reset() { diff --git a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h index fbb550b1c..80eb0e344 100755 --- a/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +++ b/hikyuu_cpp/hikyuu/utilities/db_connect/mysql/MySQLStatement.h @@ -60,7 +60,7 @@ class HKU_UTILS_API MySQLStatement : public SQLStatementBase { virtual void sub_getColumnAsBlob(int idx, std::vector &item) override; private: - bool _prepare(DBConnectBase *driver) noexcept; + void _prepare(DBConnectBase *driver); void _reset(); void _bindResult();