hikyuu 2.5.5__py3-none-win_amd64.whl → 2.6.0__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hikyuu/__init__.py +15 -0
- hikyuu/__init__.pyi +524 -516
- hikyuu/analysis/__init__.pyi +497 -490
- hikyuu/analysis/analysis.pyi +498 -491
- hikyuu/core.pyi +499 -492
- hikyuu/cpp/__init__.pyi +2 -2
- hikyuu/cpp/core310.pyd +0 -0
- hikyuu/cpp/core310.pyi +153 -21
- hikyuu/cpp/core311.pyd +0 -0
- hikyuu/cpp/core311.pyi +153 -21
- hikyuu/cpp/core312.pyd +0 -0
- hikyuu/cpp/core312.pyi +153 -21
- hikyuu/cpp/core313.pyd +0 -0
- hikyuu/cpp/core313.pyi +152 -21
- hikyuu/cpp/core39.pyd +0 -0
- hikyuu/cpp/core39.pyi +153 -21
- hikyuu/cpp/hikyuu.dll +0 -0
- hikyuu/cpp/hikyuu.lib +0 -0
- hikyuu/cpp/sqlite3.dll +0 -0
- hikyuu/data/tdx_to_mysql.py +15 -15
- hikyuu/draw/drawplot/__init__.py +2 -0
- hikyuu/draw/drawplot/__init__.pyi +9 -8
- hikyuu/draw/drawplot/bokeh_draw.pyi +514 -507
- hikyuu/draw/drawplot/common.pyi +1 -1
- hikyuu/draw/drawplot/echarts_draw.pyi +516 -509
- hikyuu/draw/drawplot/matplotlib_draw.py +80 -0
- hikyuu/draw/drawplot/matplotlib_draw.pyi +535 -518
- hikyuu/draw/elder.pyi +11 -11
- hikyuu/draw/kaufman.pyi +18 -18
- hikyuu/draw/volume.pyi +10 -10
- hikyuu/examples/notebook/002-HowToGetStock.ipynb +1 -1
- hikyuu/examples/notebook/004-IndicatorOverview.ipynb +117 -52
- hikyuu/extend.pyi +507 -501
- hikyuu/gui/HikyuuTDX.py +19 -3
- hikyuu/gui/data/MainWindow.py +87 -24
- hikyuu/gui/data/UseTdxImportToH5Thread.py +2 -2
- hikyuu/gui/dataserver.py +25 -0
- hikyuu/gui/images/star.png +0 -0
- hikyuu/hub.py +7 -13
- hikyuu/hub.pyi +9 -6
- hikyuu/include/hikyuu/StockManager.h +23 -0
- hikyuu/include/hikyuu/global/agent/spot_generated.h +3 -3
- hikyuu/include/hikyuu/plugin/__init__.py +1 -0
- hikyuu/include/hikyuu/plugin/backtest.h +37 -0
- hikyuu/include/hikyuu/plugin/dataserver.h +18 -0
- hikyuu/include/hikyuu/plugin/device.h +29 -0
- hikyuu/include/hikyuu/plugin/interface/BackTestPluginInterface.h +26 -0
- hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +23 -0
- hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +25 -0
- hikyuu/include/hikyuu/plugin/interface/__init__.py +1 -0
- hikyuu/include/hikyuu/plugin/interface/plugins.h +20 -0
- hikyuu/include/hikyuu/python/pybind_utils.h +8 -0
- hikyuu/include/hikyuu/strategy/BrokerTradeManager.h +2 -1
- hikyuu/include/hikyuu/strategy/RunPortfolioInStrategy.h +1 -0
- hikyuu/include/hikyuu/strategy/Strategy.h +96 -16
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +4 -2
- hikyuu/include/hikyuu/trade_sys/system/imp/WalkForwardTradeManager.h +3 -2
- hikyuu/include/hikyuu/utilities/config.h +1 -1
- hikyuu/include/hikyuu/utilities/datetime/Datetime.h +3 -3
- hikyuu/include/hikyuu/utilities/datetime/TimeDelta.h +8 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginBase.h +47 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginClient.h +55 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +117 -0
- hikyuu/include/hikyuu/utilities/plugin/PluginManager.h +72 -0
- hikyuu/include/hikyuu/utilities/plugin/__init__.py +1 -0
- hikyuu/include/hikyuu/utilities/thread/MQStealThreadPool.h +1 -1
- hikyuu/include/hikyuu/utilities/thread/MQThreadPool.h +1 -1
- hikyuu/include/hikyuu/utilities/thread/StealThreadPool.h +1 -1
- hikyuu/include/hikyuu/utilities/thread/ThreadPool.h +1 -1
- hikyuu/include/hikyuu/version.h +5 -5
- hikyuu/indicator/indicator.py +1 -1
- hikyuu/plugin/__init__.py +1 -0
- hikyuu/plugin/backtest.dll +0 -0
- hikyuu/plugin/dataserver.dll +0 -0
- hikyuu/plugin/device.dll +0 -0
- hikyuu/strategy/strategy_demo1.py +7 -8
- hikyuu/strategy/strategy_demo2.py +1 -1
- hikyuu/trade_manage/__init__.pyi +513 -506
- hikyuu/trade_manage/broker.pyi +3 -3
- hikyuu/trade_manage/broker_easytrader.pyi +1 -1
- hikyuu/trade_manage/trade.pyi +513 -506
- hikyuu/util/__init__.pyi +2 -2
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/METADATA +6 -2
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/RECORD +90 -73
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/entry_points.txt +1 -0
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/top_level.txt +5 -0
- hikyuu/cpp/core38.pyd +0 -0
- hikyuu/cpp/core38.pyi +0 -13172
- hikyuu/examples/notebook/011-PyechartsDrawplot.ipynb +0 -21821
- /hikyuu/gui/{hikyuu_small.png → images/hikyuu_small.png} +0 -0
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/LICENSE +0 -0
- {hikyuu-2.5.5.dist-info → hikyuu-2.6.0.dist-info}/WHEEL +0 -0
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
10
|
#include <future>
|
|
11
|
+
#include <forward_list>
|
|
11
12
|
#include "hikyuu/DataType.h"
|
|
12
13
|
#include "hikyuu/StrategyContext.h"
|
|
13
14
|
#include "hikyuu/global/SpotRecord.h"
|
|
@@ -34,7 +35,8 @@ public:
|
|
|
34
35
|
Strategy();
|
|
35
36
|
explicit Strategy(const string& name, const string& config_file = "");
|
|
36
37
|
Strategy(const vector<string>& codeList, const vector<KQuery::KType>& ktypeList,
|
|
37
|
-
const string
|
|
38
|
+
const unordered_map<string, int>& preloadNum = {}, const string& name = "Strategy",
|
|
39
|
+
const string& config_file = "");
|
|
38
40
|
explicit Strategy(const StrategyContext& context, const string& name = "Strategy",
|
|
39
41
|
const string& config_file = "");
|
|
40
42
|
|
|
@@ -55,14 +57,16 @@ public:
|
|
|
55
57
|
return m_context;
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
bool running() const;
|
|
61
|
+
|
|
58
62
|
/**
|
|
59
63
|
* 每日开盘时间内,以 delta 为周期循环定时执行指定任务
|
|
60
64
|
* @param func 待执行的任务
|
|
61
65
|
* @param delta 间隔时间
|
|
62
|
-
* @param market
|
|
66
|
+
* @param market 指定的市场, 用于获取开/收盘时间
|
|
63
67
|
* @param ignoreMarket 是否忽略市场时间限制,如为 true,则为定时循环不受开闭市时间限制
|
|
64
68
|
*/
|
|
65
|
-
void runDaily(std::function<void()
|
|
69
|
+
void runDaily(const std::function<void(Strategy*)>& func, const TimeDelta& delta,
|
|
66
70
|
const std::string& market = "SH", bool ignoreMarket = false);
|
|
67
71
|
|
|
68
72
|
/**
|
|
@@ -71,7 +75,7 @@ public:
|
|
|
71
75
|
* @param delta 指定时刻
|
|
72
76
|
* @param ignoreHoliday 忽略节假日,即节假日不执行
|
|
73
77
|
*/
|
|
74
|
-
void runDailyAt(std::function<void()
|
|
78
|
+
void runDailyAt(const std::function<void(Strategy*)>& func, const TimeDelta& delta,
|
|
75
79
|
bool ignoreHoliday = true);
|
|
76
80
|
|
|
77
81
|
/**
|
|
@@ -79,7 +83,8 @@ public:
|
|
|
79
83
|
* @note 通常用于调试。且只要收到行情采集消息就会触发,不受开、闭市时间限制
|
|
80
84
|
* @param changeFunc 回调函数
|
|
81
85
|
*/
|
|
82
|
-
void onChange(
|
|
86
|
+
void onChange(
|
|
87
|
+
const std::function<void(Strategy*, const Stock&, const SpotRecord& spot)>& changeFunc);
|
|
83
88
|
|
|
84
89
|
/**
|
|
85
90
|
* 一批行情数据接受完毕后通知
|
|
@@ -87,36 +92,111 @@ public:
|
|
|
87
92
|
* 且只要收到行情采集消息就会触发,不受开、闭市时间限制。
|
|
88
93
|
* @param recievedFucn 回调函数
|
|
89
94
|
*/
|
|
90
|
-
void onReceivedSpot(std::function<void(const Datetime&)
|
|
95
|
+
void onReceivedSpot(const std::function<void(Strategy*, const Datetime&)>& recievedFucn);
|
|
91
96
|
|
|
92
97
|
/**
|
|
93
98
|
* 启动策略执行,必须在已注册相关处理函数后执行
|
|
94
99
|
*/
|
|
95
100
|
void start(bool autoRecieveSpot = true);
|
|
96
101
|
|
|
97
|
-
|
|
102
|
+
//==========================================================================
|
|
103
|
+
// 以下为策略运行时对外接口,建议使用这些接口代替同名其他功能函数,已保证回测和实盘一致
|
|
104
|
+
//==========================================================================
|
|
105
|
+
|
|
106
|
+
TradeManagerPtr getTM() const noexcept {
|
|
107
|
+
return m_tm;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void setTM(const TradeManagerPtr& tm) noexcept {
|
|
111
|
+
m_tm = tm;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** 仅在回测状态下使用 */
|
|
115
|
+
SlippagePtr getSP() const noexcept {
|
|
116
|
+
return m_sp;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
void setSP(const SlippagePtr& slippage) noexcept {
|
|
120
|
+
m_sp = slippage;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
KData getKData(const Stock& stk, const Datetime& start_date, const Datetime& end_date,
|
|
124
|
+
const KQuery::KType& ktype,
|
|
125
|
+
KQuery::RecoverType recover_type = KQuery::NO_RECOVER) const {
|
|
126
|
+
return stk.getKData(KQueryByDate(start_date, end_date, ktype, recover_type));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
KData getLastKData(const Stock& stk, const Datetime& start_date, const KQuery::KType& ktype,
|
|
130
|
+
KQuery::RecoverType recover_type = KQuery::NO_RECOVER) const {
|
|
131
|
+
return getKData(stk, start_date, Null<Datetime>(), ktype, recover_type);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
KData getLastKData(const Stock& stk, size_t lastnum, const KQuery::KType& ktype,
|
|
135
|
+
KQuery::RecoverType recover_type = KQuery::NO_RECOVER) const;
|
|
136
|
+
|
|
137
|
+
virtual Datetime today() const {
|
|
138
|
+
return Datetime::today();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
virtual Datetime now() const {
|
|
142
|
+
return Datetime::now();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
virtual Datetime nextDatetime() const {
|
|
146
|
+
return Null<Datetime>();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
virtual TradeRecord buy(const Stock& stk, price_t price, double num, double stoploss = 0.0,
|
|
150
|
+
double goal_price = 0.0,
|
|
151
|
+
SystemPart part_from = SystemPart::PART_SIGNAL) {
|
|
152
|
+
HKU_ASSERT(m_tm);
|
|
153
|
+
return m_tm->buy(Datetime::now(), stk, price, num, stoploss, goal_price, price, part_from);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
virtual TradeRecord sell(const Stock& stk, price_t price, double num, price_t stoploss = 0.0,
|
|
157
|
+
price_t goal_price = 0.0,
|
|
158
|
+
SystemPart part_from = SystemPart::PART_SIGNAL) {
|
|
159
|
+
HKU_ASSERT(m_tm);
|
|
160
|
+
return m_tm->sell(Datetime::now(), stk, price, num, stoploss, goal_price, price, part_from);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
virtual bool isBacktesting() const {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
protected:
|
|
98
168
|
string m_name;
|
|
99
169
|
string m_config_file;
|
|
100
170
|
StrategyContext m_context;
|
|
101
|
-
|
|
102
|
-
|
|
171
|
+
TradeManagerPtr m_tm;
|
|
172
|
+
SlippagePtr m_sp;
|
|
173
|
+
|
|
174
|
+
std::function<void(Strategy*, const Datetime&)> m_on_recieved_spot;
|
|
175
|
+
std::function<void(Strategy*, const Stock&, const SpotRecord& spot)> m_on_change;
|
|
176
|
+
|
|
177
|
+
struct RunDailyAt {
|
|
178
|
+
std::function<void()> func;
|
|
179
|
+
TimeDelta delta;
|
|
180
|
+
string market;
|
|
181
|
+
bool ignoreMarket{false};
|
|
182
|
+
};
|
|
183
|
+
std::forward_list<RunDailyAt> m_run_daily_at_list;
|
|
184
|
+
|
|
185
|
+
std::unordered_map<TimeDelta, std::function<void()>> m_run_daily_at_funcs;
|
|
103
186
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
string m_run_daily_market;
|
|
107
|
-
bool m_ignoreMarket{false};
|
|
187
|
+
protected:
|
|
188
|
+
static std::atomic_bool ms_keep_running;
|
|
108
189
|
|
|
109
|
-
|
|
190
|
+
protected:
|
|
191
|
+
void _init();
|
|
110
192
|
|
|
111
193
|
private:
|
|
112
194
|
void _initParam();
|
|
113
|
-
void _init();
|
|
114
195
|
void _receivedSpot(const SpotRecord& spot);
|
|
115
196
|
void _runDaily();
|
|
116
197
|
void _runDailyAt();
|
|
117
198
|
|
|
118
199
|
private:
|
|
119
|
-
static std::atomic_bool ms_keep_running;
|
|
120
200
|
static void sig_handler(int sig);
|
|
121
201
|
|
|
122
202
|
typedef FuncWrapper event_type;
|
|
@@ -697,8 +697,10 @@ public:
|
|
|
697
697
|
/**
|
|
698
698
|
* 从订单代理实例同步当前账户资产信息(包含资金、持仓等)
|
|
699
699
|
* @param broker 订单代理实例
|
|
700
|
+
* @param datetime 同步时,通常为当前时间(Null),也可以强制为指定的时间点
|
|
700
701
|
*/
|
|
701
|
-
virtual void fetchAssetInfoFromBroker(const OrderBrokerPtr& broker
|
|
702
|
+
virtual void fetchAssetInfoFromBroker(const OrderBrokerPtr& broker,
|
|
703
|
+
const Datetime& datetime = Null<Datetime>()) {
|
|
702
704
|
HKU_WARN("The subclass does not implement this method");
|
|
703
705
|
}
|
|
704
706
|
|
|
@@ -706,7 +708,7 @@ protected:
|
|
|
706
708
|
string m_name; // 账户名称
|
|
707
709
|
TradeCostPtr m_costfunc; // 成本算法
|
|
708
710
|
|
|
709
|
-
Datetime m_broker_last_datetime;
|
|
711
|
+
Datetime m_broker_last_datetime; // 订单代理最近一次执行操作的时刻,当前启动运行时间
|
|
710
712
|
list<OrderBrokerPtr> m_broker_list; // 订单代理列表
|
|
711
713
|
|
|
712
714
|
//============================================
|
|
@@ -437,8 +437,9 @@ public:
|
|
|
437
437
|
* 从订单代理实例同步当前账户资产信息(包含资金、持仓等)
|
|
438
438
|
* @param broker 订单代理实例
|
|
439
439
|
*/
|
|
440
|
-
virtual void fetchAssetInfoFromBroker(const OrderBrokerPtr& broker
|
|
441
|
-
|
|
440
|
+
virtual void fetchAssetInfoFromBroker(const OrderBrokerPtr& broker,
|
|
441
|
+
const Datetime& datetime = Null<Datetime>()) override {
|
|
442
|
+
m_tm->fetchAssetInfoFromBroker(broker, datetime);
|
|
442
443
|
}
|
|
443
444
|
|
|
444
445
|
private:
|
|
@@ -299,9 +299,9 @@ typedef std::vector<Datetime> DatetimeList;
|
|
|
299
299
|
|
|
300
300
|
/**
|
|
301
301
|
* 获取指定范围的日历日期列表[start,end),仅仅是日,不含时分秒。
|
|
302
|
-
* @note
|
|
302
|
+
* @note 如果指定的结束日期过大,可能会耗费大量内存
|
|
303
303
|
* @param start 起始日期
|
|
304
|
-
* @param end
|
|
304
|
+
* @param end 结束日期, 如果为空,将使用 Datetime::max
|
|
305
305
|
* @return [start, end)范围内的日历日期
|
|
306
306
|
*/
|
|
307
307
|
DatetimeList HKU_UTILS_API getDateRange(const Datetime &start, const Datetime &end);
|
|
@@ -412,7 +412,7 @@ template <>
|
|
|
412
412
|
class hash<hku::Datetime> {
|
|
413
413
|
public:
|
|
414
414
|
size_t operator()(hku::Datetime const &d) const noexcept {
|
|
415
|
-
return d.ticks();
|
|
415
|
+
return std::hash<uint64_t>()(d.ticks());
|
|
416
416
|
}
|
|
417
417
|
};
|
|
418
418
|
|
|
@@ -320,6 +320,14 @@ inline TimeDelta Microseconds(int64_t microsecs) {
|
|
|
320
320
|
|
|
321
321
|
namespace std {
|
|
322
322
|
|
|
323
|
+
template <>
|
|
324
|
+
class hash<hku::TimeDelta> {
|
|
325
|
+
public:
|
|
326
|
+
size_t operator()(hku::TimeDelta const &d) const noexcept {
|
|
327
|
+
return std::hash<int64_t>()(d.ticks());
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
323
331
|
inline string to_string(const hku::TimeDelta &delta) {
|
|
324
332
|
return delta.str();
|
|
325
333
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2025-03-18
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
#ifndef HKU_UTILS_PLUGIN_BASE_H_
|
|
10
|
+
#define HKU_UTILS_PLUGIN_BASE_H_
|
|
11
|
+
|
|
12
|
+
#include <string>
|
|
13
|
+
#include "hikyuu/utilities/config.h"
|
|
14
|
+
#include "hikyuu/utilities/osdef.h"
|
|
15
|
+
|
|
16
|
+
namespace hku {
|
|
17
|
+
|
|
18
|
+
class PluginBase {
|
|
19
|
+
public:
|
|
20
|
+
PluginBase() = default;
|
|
21
|
+
virtual ~PluginBase() = default;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @brief 返回插件信息
|
|
25
|
+
* @details
|
|
26
|
+
* 插件信息为json格式,包含name(string)、version(int)、description(string)、author(string)字段
|
|
27
|
+
* 如:{"name":"unknown","version": 1.0,"description":"","author":"unknown"}
|
|
28
|
+
* @return std::string
|
|
29
|
+
*/
|
|
30
|
+
virtual std::string info() const noexcept = 0;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
} // namespace hku
|
|
34
|
+
|
|
35
|
+
#if HKU_OS_WINDOWS
|
|
36
|
+
#define HKU_PLUGIN_DEFINE(plugin) \
|
|
37
|
+
extern "C" __declspec(dllexport) hku::PluginBase* createPlugin() { \
|
|
38
|
+
return new plugin(); \
|
|
39
|
+
}
|
|
40
|
+
#else
|
|
41
|
+
#define HKU_PLUGIN_DEFINE(plugin) \
|
|
42
|
+
extern "C" hku::PluginBase* createPlugin() { \
|
|
43
|
+
return new plugin(); \
|
|
44
|
+
}
|
|
45
|
+
#endif
|
|
46
|
+
|
|
47
|
+
#endif /* HKU_UTILS_PLUGIN_BASE_H_ */
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2025-04-06
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "PluginLoader.h"
|
|
11
|
+
|
|
12
|
+
namespace hku {
|
|
13
|
+
|
|
14
|
+
template <typename InterfaceT>
|
|
15
|
+
class PluginClient : public InterfaceT {
|
|
16
|
+
public:
|
|
17
|
+
PluginClient() = delete;
|
|
18
|
+
PluginClient(const std::string &path, const std::string &filename) {
|
|
19
|
+
m_loader = std::make_unique<PluginLoader>(path);
|
|
20
|
+
HKU_CHECK(m_loader->load(filename), "load plugin failed! {}/{}", path, filename);
|
|
21
|
+
m_impl = m_loader->instance<InterfaceT>();
|
|
22
|
+
}
|
|
23
|
+
virtual ~PluginClient() = default;
|
|
24
|
+
|
|
25
|
+
PluginClient(const PluginClient &) = delete;
|
|
26
|
+
PluginClient &operator=(const PluginClient &) = delete;
|
|
27
|
+
|
|
28
|
+
PluginClient(PluginClient &&rhs) : m_impl(rhs.m_impl), m_loader(std::move(rhs.m_loader)) {
|
|
29
|
+
rhs.m_impl = nullptr;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
PluginClient &operator=(PluginClient &&rhs) {
|
|
33
|
+
if (this != &rhs) {
|
|
34
|
+
m_loader = std::move(rhs.m_loader);
|
|
35
|
+
m_impl = rhs.m_impl;
|
|
36
|
+
rhs.m_impl = nullptr;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::string info() const noexcept override {
|
|
41
|
+
return m_impl->info();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
InterfaceT *getPlugin() const {
|
|
45
|
+
return m_impl;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected:
|
|
49
|
+
InterfaceT *m_impl{nullptr};
|
|
50
|
+
|
|
51
|
+
protected:
|
|
52
|
+
std::unique_ptr<PluginLoader> m_loader;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
} // namespace hku
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2025-03-18
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
#ifndef HKU_UTILS_PLUGIN_LOADER_H_
|
|
10
|
+
#define HKU_UTILS_PLUGIN_LOADER_H_
|
|
11
|
+
|
|
12
|
+
#include <mutex>
|
|
13
|
+
#include <string>
|
|
14
|
+
#include <memory>
|
|
15
|
+
#include "hikyuu/utilities/config.h"
|
|
16
|
+
#include "hikyuu/utilities/osdef.h"
|
|
17
|
+
#include "hikyuu/utilities/os.h"
|
|
18
|
+
#include "hikyuu/utilities/Log.h"
|
|
19
|
+
#include "PluginBase.h"
|
|
20
|
+
|
|
21
|
+
#if HKU_OS_WINDOWS
|
|
22
|
+
#include <windows.h>
|
|
23
|
+
#else
|
|
24
|
+
#include <dlfcn.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
namespace hku {
|
|
28
|
+
|
|
29
|
+
class PluginLoader final {
|
|
30
|
+
public:
|
|
31
|
+
PluginLoader() : PluginLoader(".") {}
|
|
32
|
+
explicit PluginLoader(const std::string& path) : m_path(path) {}
|
|
33
|
+
|
|
34
|
+
PluginLoader(const PluginLoader&) = delete;
|
|
35
|
+
PluginLoader(PluginLoader&&) = delete;
|
|
36
|
+
|
|
37
|
+
~PluginLoader() {
|
|
38
|
+
unload();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
template <typename T>
|
|
42
|
+
T* instance() const noexcept {
|
|
43
|
+
HKU_IF_RETURN(!m_plugin, nullptr);
|
|
44
|
+
return dynamic_cast<T*>(m_plugin.get());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
bool load(const std::string& pluginname) noexcept {
|
|
48
|
+
std::string filename = getFileName(pluginname);
|
|
49
|
+
HKU_WARN_IF_RETURN(!existFile(filename), false, "file({}) not exist!", filename);
|
|
50
|
+
|
|
51
|
+
#if HKU_OS_WINDOWS
|
|
52
|
+
m_handle = LoadLibrary(HKU_PATH(filename).c_str());
|
|
53
|
+
#else
|
|
54
|
+
m_handle = dlopen(filename.c_str(), RTLD_LAZY);
|
|
55
|
+
#endif
|
|
56
|
+
HKU_WARN_IF_RETURN(!m_handle, false, "load plugin({}) failed!", filename);
|
|
57
|
+
|
|
58
|
+
typedef PluginBase* (*CreateFunction)();
|
|
59
|
+
CreateFunction createFunction =
|
|
60
|
+
reinterpret_cast<CreateFunction>(getFunciton("createPlugin"));
|
|
61
|
+
HKU_WARN_IF_RETURN(!createFunction, false, "Failed to get plugin({}) handle!", filename);
|
|
62
|
+
|
|
63
|
+
m_plugin.reset(createFunction());
|
|
64
|
+
if (!m_plugin) {
|
|
65
|
+
HKU_ERROR("Failed to create plugin ({})!", filename);
|
|
66
|
+
unload();
|
|
67
|
+
m_plugin.reset();
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private:
|
|
75
|
+
void unload() noexcept {
|
|
76
|
+
m_plugin.reset();
|
|
77
|
+
if (m_handle) {
|
|
78
|
+
#if HKU_OS_WINDOWS
|
|
79
|
+
FreeLibrary(m_handle);
|
|
80
|
+
#else
|
|
81
|
+
dlclose(m_handle);
|
|
82
|
+
#endif
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void* getFunciton(const char* symbol) noexcept {
|
|
87
|
+
#if HKU_OS_WINDOWS
|
|
88
|
+
void* func = GetProcAddress(m_handle, symbol);
|
|
89
|
+
#else
|
|
90
|
+
void* func = dlsym(m_handle, symbol);
|
|
91
|
+
#endif
|
|
92
|
+
return func;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
std::string getFileName(const std::string& pluginname) const noexcept {
|
|
96
|
+
#if HKU_OS_WINDOWS
|
|
97
|
+
return fmt::format("{}/{}.dll", m_path, pluginname);
|
|
98
|
+
#elif HKU_OS_LINUX
|
|
99
|
+
return fmt::format("{}/lib{}.so", m_path, pluginname);
|
|
100
|
+
#elif HKU_OS_OSX
|
|
101
|
+
return fmt::format("{}/lib{}.dylib", m_path, pluginname);
|
|
102
|
+
#endif
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private:
|
|
106
|
+
#if HKU_OS_WINDOWS
|
|
107
|
+
HMODULE m_handle{nullptr};
|
|
108
|
+
#else
|
|
109
|
+
void* m_handle{nullptr};
|
|
110
|
+
#endif
|
|
111
|
+
std::string m_path;
|
|
112
|
+
std::unique_ptr<PluginBase> m_plugin{nullptr};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
} // namespace hku
|
|
116
|
+
|
|
117
|
+
#endif /* HKU_UTILS_PLUGIN_LOADER_H_ */
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 hikyuu.org
|
|
3
|
+
*
|
|
4
|
+
* Created on: 2025-04-10
|
|
5
|
+
* Author: fasiondog
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <memory>
|
|
12
|
+
#include <unordered_map>
|
|
13
|
+
#include <mutex>
|
|
14
|
+
#include "hikyuu/utilities/Log.h"
|
|
15
|
+
#include "hikyuu/utilities/plugin/PluginLoader.h"
|
|
16
|
+
|
|
17
|
+
namespace hku {
|
|
18
|
+
|
|
19
|
+
class PluginManager final {
|
|
20
|
+
public:
|
|
21
|
+
PluginManager() : m_plugin_path(".") {};
|
|
22
|
+
explicit PluginManager(const std::string& plugin_path) : m_plugin_path(plugin_path) {}
|
|
23
|
+
|
|
24
|
+
~PluginManager() = default;
|
|
25
|
+
PluginManager(const PluginManager&) = delete;
|
|
26
|
+
PluginManager(PluginManager&&) = delete;
|
|
27
|
+
PluginManager& operator=(const PluginManager&) = delete;
|
|
28
|
+
PluginManager& operator=(PluginManager&&) = delete;
|
|
29
|
+
|
|
30
|
+
const std::string& pluginPath() const noexcept {
|
|
31
|
+
return m_plugin_path;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void pluginPath(const std::string& plugin_path) noexcept {
|
|
35
|
+
HKU_TRACE_IF_RETURN(!m_plugins.empty(), void(),
|
|
36
|
+
"Existing loaded plugins, Ignore set plugin path: {}, ", plugin_path);
|
|
37
|
+
m_plugin_path = plugin_path;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
template <typename PluginInterfaceT>
|
|
41
|
+
PluginInterfaceT* getPlugin(const std::string& pluginname) noexcept;
|
|
42
|
+
|
|
43
|
+
private:
|
|
44
|
+
std::unordered_map<std::string, std::unique_ptr<PluginLoader>>::iterator load(
|
|
45
|
+
const std::string& pluginname) noexcept {
|
|
46
|
+
std::lock_guard<std::mutex> lock(m_mutex);
|
|
47
|
+
std::unique_ptr<PluginLoader> loader = std::make_unique<PluginLoader>(m_plugin_path);
|
|
48
|
+
if (loader->load(pluginname)) {
|
|
49
|
+
auto [it, success] = m_plugins.insert(std::make_pair(pluginname, std::move(loader)));
|
|
50
|
+
if (success) {
|
|
51
|
+
return it;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return m_plugins.end();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private:
|
|
58
|
+
std::string m_plugin_path;
|
|
59
|
+
std::unordered_map<std::string, std::unique_ptr<PluginLoader>> m_plugins;
|
|
60
|
+
std::mutex m_mutex;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
template <typename PluginInterfaceT>
|
|
64
|
+
PluginInterfaceT* PluginManager::getPlugin(const std::string& pluginname) noexcept {
|
|
65
|
+
auto it = m_plugins.find(pluginname);
|
|
66
|
+
if (it == m_plugins.end()) {
|
|
67
|
+
it = load(pluginname);
|
|
68
|
+
}
|
|
69
|
+
return it != m_plugins.end() ? it->second->instance<PluginInterfaceT>() : nullptr;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
} // namespace hku
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -242,7 +242,7 @@ private:
|
|
|
242
242
|
std::vector<std::thread> m_threads; // 工作线程
|
|
243
243
|
|
|
244
244
|
// 线程本地变量
|
|
245
|
-
#if CPP_STANDARD >= CPP_STANDARD_17
|
|
245
|
+
#if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
|
|
246
246
|
inline static thread_local MQStealQueue<task_type>* m_local_work_queue =
|
|
247
247
|
nullptr; // 本地任务队列
|
|
248
248
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
@@ -235,7 +235,7 @@ private:
|
|
|
235
235
|
std::vector<std::thread> m_threads; // 工作线程
|
|
236
236
|
|
|
237
237
|
// 线程本地变量
|
|
238
|
-
#if CPP_STANDARD >= CPP_STANDARD_17
|
|
238
|
+
#if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
|
|
239
239
|
inline static thread_local ThreadSafeQueue<task_type>* m_local_work_queue =
|
|
240
240
|
nullptr; // 本地任务队列
|
|
241
241
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
@@ -239,7 +239,7 @@ private:
|
|
|
239
239
|
std::vector<std::thread> m_threads; // 工作线程
|
|
240
240
|
|
|
241
241
|
// 线程本地变量
|
|
242
|
-
#if CPP_STANDARD >= CPP_STANDARD_17
|
|
242
|
+
#if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
|
|
243
243
|
inline static thread_local WorkStealQueue* m_local_work_queue = nullptr; // 本地任务队列
|
|
244
244
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
245
245
|
inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
@@ -193,7 +193,7 @@ private:
|
|
|
193
193
|
std::vector<InterruptFlag*> m_interrupt_flags; // 线程中断标志
|
|
194
194
|
|
|
195
195
|
// 线程本地变量
|
|
196
|
-
#if CPP_STANDARD >= CPP_STANDARD_17
|
|
196
|
+
#if CPP_STANDARD >= CPP_STANDARD_17 && !defined(__clang__)
|
|
197
197
|
inline static thread_local InterruptFlag m_thread_need_stop; // 线程停止运行指示
|
|
198
198
|
inline static thread_local int m_index = -1; // 在线程池中的序号
|
|
199
199
|
#else
|
hikyuu/include/hikyuu/version.h
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
#define HKU_VERSION_H
|
|
13
13
|
|
|
14
14
|
// clang-format off
|
|
15
|
-
#define HKU_VERSION "2.
|
|
15
|
+
#define HKU_VERSION "2.6.0"
|
|
16
16
|
#define HKU_VERSION_MAJOR 2
|
|
17
|
-
#define HKU_VERSION_MINOR
|
|
18
|
-
#define HKU_VERSION_ALTER
|
|
19
|
-
#define HKU_VERSION_BUILD
|
|
17
|
+
#define HKU_VERSION_MINOR 6
|
|
18
|
+
#define HKU_VERSION_ALTER 0
|
|
19
|
+
#define HKU_VERSION_BUILD 202504301710
|
|
20
20
|
#define HKU_VERSION_MODE "RELEASE"
|
|
21
|
-
#define HKU_VERSION_GIT "2.
|
|
21
|
+
#define HKU_VERSION_GIT "2.6.0 release.3bd470a3 (RELEASE)"
|
|
22
22
|
// clang-format on
|
|
23
23
|
|
|
24
24
|
#endif /* HKU_VERSION_H */
|
hikyuu/indicator/indicator.py
CHANGED
|
@@ -90,7 +90,7 @@ def concat_to_df(dates, ind_list, head_stock_code=True, head_ind_name=False):
|
|
|
90
90
|
示例:
|
|
91
91
|
query = Query(-200)
|
|
92
92
|
k_list = [stk.get_kdata(query) for stk in [sm['sz000001'], sm['sz000002']]]
|
|
93
|
-
ma_list = [MA(k) for k in k_list]
|
|
93
|
+
ma_list = [MA(CLOSE(k)) for k in k_list]
|
|
94
94
|
concat_to_df(sm.get_trading_calendar(query), ma_list, head_stock_code=True, head_ind_name=False)
|
|
95
95
|
|
|
96
96
|
输出:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
Binary file
|
|
Binary file
|
hikyuu/plugin/device.dll
ADDED
|
Binary file
|
|
@@ -7,24 +7,23 @@
|
|
|
7
7
|
# 供自行实现程序化交易时参考,请自行负责程序化交易可能造成的损失。
|
|
8
8
|
#
|
|
9
9
|
|
|
10
|
-
from hikyuu import
|
|
11
|
-
from hikyuu import sm
|
|
10
|
+
from hikyuu import *
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
def on_change(stk, spot):
|
|
13
|
+
def on_change(stg: Strategy, stk: Stock, spot: SpotRecord):
|
|
15
14
|
print("[on_change]:", stk.market_code, stk.name, spot.close, spot.bid1, spot.ask1)
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
def on_spot(rev_time):
|
|
17
|
+
def on_spot(stg: Strategy, rev_time: Datetime):
|
|
19
18
|
print("[on_received_spot] rev_time:", rev_time)
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
def my_func1():
|
|
23
|
-
print("[my_func1]", str(
|
|
21
|
+
def my_func1(stg: Strategy):
|
|
22
|
+
print("[my_func1]", str(stg.now()))
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
def my_func2():
|
|
27
|
-
print("[my_func2] calculate:",
|
|
25
|
+
def my_func2(stg: Strategy):
|
|
26
|
+
print("[my_func2] calculate:", stg.now())
|
|
28
27
|
for s in sm:
|
|
29
28
|
print(s)
|
|
30
29
|
|