mirror of
https://gitee.com/fasiondog/hikyuu.git
synced 2024-11-30 02:48:57 +08:00
Merge branch 'master' of https://github.com/fasiondog/hikyuu into feature/stg
This commit is contained in:
commit
8452b1a0b3
@ -7,11 +7,11 @@ from hikyuu import sm
|
||||
|
||||
|
||||
def on_change(stk, spot):
|
||||
print(stk.market_code, stk.name, spot.close, spot.bid1, spot.ask1)
|
||||
print("[on_change]:", stk.market_code, stk.name, spot.close, spot.bid1, spot.ask1)
|
||||
|
||||
|
||||
def on_spot(rev_time):
|
||||
print("rev_time:", rev_time)
|
||||
print("[on_received_spot] rev_time:", rev_time)
|
||||
|
||||
|
||||
def my_func():
|
||||
@ -24,8 +24,8 @@ def my_func():
|
||||
# 以 Strategy 方式运行示例
|
||||
if __name__ == '__main__':
|
||||
s = Strategy(['sh600000', 'sz000001'], [Query.MIN, Query.DAY])
|
||||
# s.run_daily_at(my_func, Datetime.now() - Datetime.today() + Seconds(5))
|
||||
# s.run_daily_at(my_func, Datetime.now() - Datetime.today() + Seconds(10), False)
|
||||
s.on_change(on_change)
|
||||
s.on_received_spot(on_spot)
|
||||
s.run_daily(my_func, Minutes(1))
|
||||
s.run_daily(my_func, Minutes(1)) # , ignore_market=True)
|
||||
s.start()
|
||||
|
@ -48,11 +48,11 @@ class OrderBrokerWrap(OrderBrokerBase):
|
||||
|
||||
def _buy(self, datetime, market, code, price, num, stoploss, goal_price, part_from):
|
||||
"""实现 OrderBrokerBase 的 _buy 接口"""
|
||||
self._broker.buy('{}{}'.format(market, code), price, num, stoploss, goal_price, part_from)
|
||||
self._broker.buy(market, code, price, num, stoploss, goal_price, part_from)
|
||||
|
||||
def _sell(self, datetime, market, code, price, num, stoploss, goal_price, part_from):
|
||||
"""实现 OrderBrokerBase 的 _sell 接口"""
|
||||
self._broker.sell('{}{}'.format(market, code), price, num, stoploss, goal_price, part_from)
|
||||
self._broker.sell(market, code, price, num, stoploss, goal_price, part_from)
|
||||
|
||||
def _get_asset_info(self):
|
||||
try:
|
||||
@ -71,11 +71,11 @@ class TestOrderBroker:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def buy(self, code, price, num, stoploss, goal_price, part_from):
|
||||
print(f"买入:{code}, 价格: {price}, 数量: {num} 预期止损价: {stoploss}, 预期目标价: {goal_price}, 信号来源: {part_from}")
|
||||
def buy(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
print(f"买入:{market}{code}, 价格: {price}, 数量: {num} 预期止损价: {stoploss}, 预期目标价: {goal_price}, 信号来源: {part_from}")
|
||||
|
||||
def sell(self, code, price, num, stoploss, goal_price, part_from):
|
||||
print(f"卖出:{code}, 价格: {price}, 数量: {num}, 信号来源: {part_from}")
|
||||
def sell(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
print(f"卖出:{market}{code}, 价格: {price}, 数量: {num}, 信号来源: {part_from}")
|
||||
|
||||
|
||||
def crtOB(broker, name="NO_NAME"):
|
||||
|
@ -12,20 +12,22 @@ class EasyTraderOrderBroker:
|
||||
self.user = user
|
||||
self.buffer = {}
|
||||
|
||||
def buy(self, code, price, num, stoploss, goal_price, part_from):
|
||||
self.user.buy(code[2:], price=price, amount=num)
|
||||
print("买入:%s %.3f %i" % (code, price, num))
|
||||
self.buffer[code] = (num, stoploss, goal_price)
|
||||
def buy(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
self.user.buy(code, price=price, amount=num)
|
||||
market_code = f"{market}{code}"
|
||||
print(f"买入:{market_code} {price} {num}")
|
||||
self.buffer[market_code] = (num, stoploss, goal_price)
|
||||
|
||||
def sell(self, code, price, num, stoploss, goal_price, part_from):
|
||||
self.user.sell(code[2:], price=price, amount=num)
|
||||
print("卖出:%s %.3f %i" % (code, price, num))
|
||||
if code in self.buffer:
|
||||
old_num = self.buffer[code][0]
|
||||
def sell(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
self.user.sell(code, price=price, amount=num)
|
||||
market_code = f"{market}{code}"
|
||||
print(f"卖出:{market_code} {price} {num}")
|
||||
if market_code in self.buffer:
|
||||
old_num = self.buffer[market_code][0]
|
||||
if old_num == num:
|
||||
self.buffer.pop(code)
|
||||
self.buffer.pop(market_code)
|
||||
else:
|
||||
self.buffer[code] = (old_num - num, stoploss, goal_price)
|
||||
self.buffer[market_code] = (old_num - num, stoploss, goal_price)
|
||||
|
||||
def get_asset_info(self):
|
||||
'''以下只适用于华泰'''
|
||||
|
@ -72,7 +72,7 @@ class MailOrderBroker:
|
||||
smtpObj.login(self._sender, self._pwd)
|
||||
smtpObj.sendmail(self._sender, self._receivers, message.as_string())
|
||||
|
||||
def buy(self, code, price, num, stoploss, goal_price, part_from):
|
||||
def buy(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
"""执行买入操作,向指定的邮箱发送邮件,格式如下::
|
||||
|
||||
邮件标题:【Hkyuu提醒】买入 证券代码
|
||||
@ -82,11 +82,11 @@ class MailOrderBroker:
|
||||
:param float price: 买入价格
|
||||
:param int num: 买入数量
|
||||
"""
|
||||
action = "买入:{},价格:{},数量:{} ".format(code, price, num)
|
||||
action = "买入:{}{},价格:{},数量:{} ".format(market, code, price, num)
|
||||
title = "【Hkyuu提醒】买入 {}".format(code)
|
||||
self._sendmail(title, action)
|
||||
|
||||
def sell(self, code, price, num, stoploss, goal_price, part_from):
|
||||
def sell(self, market, code, price, num, stoploss, goal_price, part_from):
|
||||
"""执行卖出操作,向指定的邮箱发送邮件,格式如下::
|
||||
|
||||
邮件标题:【Hkyuu提醒】卖出 证券代码
|
||||
@ -96,6 +96,6 @@ class MailOrderBroker:
|
||||
:param float price: 卖出价格
|
||||
:param int num: 卖出数量
|
||||
"""
|
||||
title = "【Hkyuu提醒】卖出 {}".format(code)
|
||||
title = "【Hkyuu提醒】卖出 {}{}".format(market, code)
|
||||
action = "卖出:{},价格:{},数量:{} ".format(code, price, num)
|
||||
self._sendmail(title, action)
|
||||
|
@ -62,9 +62,7 @@ Strategy::~Strategy() {
|
||||
CLS_INFO("Quit Strategy {}!", m_name);
|
||||
}
|
||||
|
||||
void Strategy::run() {
|
||||
CLS_IF_RETURN(m_running, void());
|
||||
|
||||
void Strategy::_init() {
|
||||
StockManager& sm = StockManager::instance();
|
||||
|
||||
// sm 尚未初始化,则初始化
|
||||
@ -85,9 +83,15 @@ void Strategy::run() {
|
||||
|
||||
// 先将行情接收代理停止,以便后面加入处理函数
|
||||
stopSpotAgent();
|
||||
}
|
||||
|
||||
void Strategy::start() {
|
||||
_init();
|
||||
|
||||
_runDailyAt();
|
||||
|
||||
auto& agent = *getGlobalSpotAgent();
|
||||
agent.addProcess([this](const SpotRecord& spot) { receivedSpot(spot); });
|
||||
agent.addProcess([this](const SpotRecord& spot) { _receivedSpot(spot); });
|
||||
agent.addPostProcess([this](Datetime revTime) {
|
||||
if (m_on_recieved_spot) {
|
||||
EVENT([=]() { m_on_recieved_spot(revTime); });
|
||||
@ -95,30 +99,23 @@ void Strategy::run() {
|
||||
});
|
||||
startSpotAgent(true);
|
||||
|
||||
m_running = true;
|
||||
}
|
||||
_runDaily();
|
||||
|
||||
void Strategy::start() {
|
||||
CLS_CHECK(m_running, "No handler functions are registered!");
|
||||
CLS_INFO("start even loop ...");
|
||||
_startEventLoop();
|
||||
}
|
||||
|
||||
void Strategy::onChange(std::function<void(const Stock&, const SpotRecord& spot)>&& changeFunc) {
|
||||
if (!m_running) {
|
||||
run();
|
||||
}
|
||||
HKU_CHECK(changeFunc, "Invalid changeFunc!");
|
||||
m_on_change = changeFunc;
|
||||
}
|
||||
|
||||
void Strategy::onReceivedSpot(std::function<void(const Datetime&)>&& recievedFucn) {
|
||||
if (!m_running) {
|
||||
run();
|
||||
}
|
||||
HKU_CHECK(recievedFucn, "Invalid recievedFucn!");
|
||||
m_on_recieved_spot = recievedFucn;
|
||||
}
|
||||
|
||||
void Strategy::receivedSpot(const SpotRecord& spot) {
|
||||
void Strategy::_receivedSpot(const SpotRecord& spot) {
|
||||
Stock stk = getStock(format("{}{}", spot.market, spot.code));
|
||||
if (!stk.isNull()) {
|
||||
if (m_on_change) {
|
||||
@ -128,14 +125,17 @@ void Strategy::receivedSpot(const SpotRecord& spot) {
|
||||
}
|
||||
|
||||
void Strategy::runDaily(std::function<void()>&& func, const TimeDelta& delta,
|
||||
const std::string& market) {
|
||||
if (!m_running) {
|
||||
run();
|
||||
}
|
||||
const std::string& market, bool ignoreMarket) {
|
||||
HKU_CHECK(func, "Invalid func!");
|
||||
m_run_daily_delta = delta;
|
||||
m_run_daily_market = market;
|
||||
m_ignoreMarket = ignoreMarket;
|
||||
|
||||
try {
|
||||
auto* scheduler = getScheduler();
|
||||
auto new_func = [=]() {
|
||||
if (ignoreMarket) {
|
||||
m_run_daily_func = [=]() { EVENT(func); };
|
||||
|
||||
} else {
|
||||
m_run_daily_func = [=]() {
|
||||
const auto& sm = StockManager::instance();
|
||||
auto today = Datetime::today();
|
||||
int day = today.dayOfWeek();
|
||||
@ -143,7 +143,7 @@ void Strategy::runDaily(std::function<void()>&& func, const TimeDelta& delta,
|
||||
return;
|
||||
}
|
||||
|
||||
auto market_info = sm.getMarketInfo(market);
|
||||
auto market_info = sm.getMarketInfo(m_run_daily_market);
|
||||
Datetime open1 = today + market_info.openTime1();
|
||||
Datetime close1 = today + market_info.closeTime1();
|
||||
Datetime open2 = today + market_info.openTime2();
|
||||
@ -153,59 +153,79 @@ void Strategy::runDaily(std::function<void()>&& func, const TimeDelta& delta,
|
||||
EVENT(func);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void Strategy::_runDaily() {
|
||||
HKU_IF_RETURN(!m_run_daily_func, void());
|
||||
|
||||
auto* scheduler = getScheduler();
|
||||
if (m_ignoreMarket) {
|
||||
scheduler->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const auto& sm = StockManager::instance();
|
||||
auto market_info = sm.getMarketInfo(market);
|
||||
auto market_info = sm.getMarketInfo(m_run_daily_market);
|
||||
auto today = Datetime::today();
|
||||
auto now = Datetime::now();
|
||||
TimeDelta now_time = now - today;
|
||||
if (now_time >= market_info.closeTime2()) {
|
||||
scheduler->addFuncAtTime(today.nextDay() + market_info.openTime1(), [=]() {
|
||||
new_func();
|
||||
m_run_daily_func();
|
||||
auto* sched = getScheduler();
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
});
|
||||
|
||||
} else if (now_time >= market_info.openTime2()) {
|
||||
int64_t ticks = now_time.ticks() - market_info.openTime2().ticks();
|
||||
int64_t delta_ticks = delta.ticks();
|
||||
int64_t delta_ticks = m_run_daily_delta.ticks();
|
||||
if (ticks % delta_ticks == 0) {
|
||||
scheduler->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
scheduler->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
} else {
|
||||
auto delay = TimeDelta::fromTicks((ticks / delta_ticks + 1) * delta_ticks - ticks);
|
||||
scheduler->addFuncAtTime(now + delay, [=]() {
|
||||
new_func();
|
||||
m_run_daily_func();
|
||||
auto* sched = getScheduler();
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
});
|
||||
}
|
||||
|
||||
} else if (now_time >= market_info.closeTime1()) {
|
||||
scheduler->addFuncAtTime(today + market_info.openTime2(), [=]() {
|
||||
new_func();
|
||||
m_run_daily_func();
|
||||
auto* sched = getScheduler();
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
});
|
||||
|
||||
} else if (now_time < market_info.closeTime1() && now_time >= market_info.openTime1()) {
|
||||
int64_t ticks = now_time.ticks() - market_info.openTime1().ticks();
|
||||
int64_t delta_ticks = delta.ticks();
|
||||
int64_t delta_ticks = m_run_daily_delta.ticks();
|
||||
if (ticks % delta_ticks == 0) {
|
||||
scheduler->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
scheduler->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
} else {
|
||||
auto delay = TimeDelta::fromTicks((ticks / delta_ticks + 1) * delta_ticks - ticks);
|
||||
scheduler->addFuncAtTime(now + delay, [=]() {
|
||||
new_func();
|
||||
m_run_daily_func();
|
||||
auto* sched = getScheduler();
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
});
|
||||
}
|
||||
|
||||
} else if (now_time < market_info.openTime1()) {
|
||||
scheduler->addFuncAtTime(today + market_info.openTime1(), [=]() {
|
||||
new_func();
|
||||
m_run_daily_func();
|
||||
auto* sched = getScheduler();
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), delta, new_func);
|
||||
sched->addDurationFunc(std::numeric_limits<int>::max(), m_run_daily_delta,
|
||||
m_run_daily_func);
|
||||
});
|
||||
|
||||
} else {
|
||||
@ -218,26 +238,29 @@ void Strategy::runDaily(std::function<void()>&& func, const TimeDelta& delta,
|
||||
|
||||
void Strategy::runDailyAt(std::function<void()>&& func, const TimeDelta& delta,
|
||||
bool ignoreHoliday) {
|
||||
if (!m_running) {
|
||||
run();
|
||||
HKU_CHECK(func, "Invalid func!");
|
||||
m_run_daily_at_delta = delta;
|
||||
|
||||
if (ignoreHoliday) {
|
||||
m_run_daily_at_func = [=]() {
|
||||
const auto& sm = StockManager::instance();
|
||||
auto today = Datetime::today();
|
||||
int day = today.dayOfWeek();
|
||||
if (day != 0 && day != 6 && !sm.isHoliday(today)) {
|
||||
EVENT(func);
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
m_run_daily_at_func = [=]() { EVENT(func); };
|
||||
}
|
||||
}
|
||||
|
||||
auto new_func = [=]() {
|
||||
if (!ignoreHoliday) {
|
||||
EVENT(func);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& sm = StockManager::instance();
|
||||
auto today = Datetime::today();
|
||||
int day = today.dayOfWeek();
|
||||
if (day != 0 && day != 6 && !sm.isHoliday(today)) {
|
||||
EVENT(func);
|
||||
}
|
||||
};
|
||||
|
||||
auto* scheduler = getScheduler();
|
||||
scheduler->addFuncAtTimeEveryDay(delta, new_func);
|
||||
void Strategy::_runDailyAt() {
|
||||
if (m_run_daily_at_func) {
|
||||
auto* scheduler = getScheduler();
|
||||
scheduler->addFuncAtTimeEveryDay(m_run_daily_at_delta, m_run_daily_at_func);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -50,9 +50,10 @@ public:
|
||||
* @param func 待执行的任务
|
||||
* @param delta 间隔时间
|
||||
* @param market 指定的市场
|
||||
* @param ignoreMarket 是否忽略市场时间限制,如为 true,则为定时循环不受开闭市时间限制
|
||||
*/
|
||||
void runDaily(std::function<void()>&& func, const TimeDelta& delta,
|
||||
const std::string& market = "SH");
|
||||
const std::string& market = "SH", bool ignoreMarket = false);
|
||||
|
||||
/**
|
||||
* 每日在指定时刻执行任务
|
||||
@ -89,11 +90,20 @@ private:
|
||||
StrategyContext m_context;
|
||||
std::function<void(const Datetime&)> m_on_recieved_spot;
|
||||
std::function<void(const Stock&, const SpotRecord& spot)> m_on_change;
|
||||
bool m_running{false};
|
||||
|
||||
std::function<void()> m_run_daily_func;
|
||||
TimeDelta m_run_daily_delta;
|
||||
string m_run_daily_market;
|
||||
bool m_ignoreMarket{false};
|
||||
|
||||
std::function<void()> m_run_daily_at_func;
|
||||
TimeDelta m_run_daily_at_delta;
|
||||
|
||||
private:
|
||||
void run();
|
||||
void receivedSpot(const SpotRecord& spot);
|
||||
void _init();
|
||||
void _receivedSpot(const SpotRecord& spot);
|
||||
void _runDaily();
|
||||
void _runDailyAt();
|
||||
|
||||
private:
|
||||
static std::atomic_bool ms_keep_running;
|
||||
|
@ -58,21 +58,25 @@ void export_Strategy(py::module& m) {
|
||||
};
|
||||
self.onReceivedSpot(new_func);
|
||||
})
|
||||
.def("run_daily",
|
||||
[](Strategy& self, py::object func, const TimeDelta& time) {
|
||||
HKU_CHECK(py::hasattr(func, "__call__"), "func is not callable!");
|
||||
py::object c_func = func.attr("__call__");
|
||||
auto new_func = [=]() {
|
||||
try {
|
||||
c_func();
|
||||
} catch (const std::exception& e) {
|
||||
HKU_ERROR(e.what());
|
||||
} catch (...) {
|
||||
HKU_ERROR("Unknown error!");
|
||||
}
|
||||
};
|
||||
self.runDaily(new_func, time);
|
||||
})
|
||||
.def(
|
||||
"run_daily",
|
||||
[](Strategy& self, py::object func, const TimeDelta& time, std::string market,
|
||||
bool ignore_market) {
|
||||
HKU_CHECK(py::hasattr(func, "__call__"), "func is not callable!");
|
||||
py::object c_func = func.attr("__call__");
|
||||
auto new_func = [=]() {
|
||||
try {
|
||||
c_func();
|
||||
} catch (const std::exception& e) {
|
||||
HKU_ERROR(e.what());
|
||||
} catch (...) {
|
||||
HKU_ERROR("Unknown error!");
|
||||
}
|
||||
};
|
||||
self.runDaily(new_func, time, market, ignore_market);
|
||||
},
|
||||
py::arg("func"), py::arg("time"), py::arg("market") = "SH",
|
||||
py::arg("ignore_market") = false)
|
||||
.def(
|
||||
"run_daily_at",
|
||||
[](Strategy& self, py::object func, const TimeDelta& time, bool ignore_holiday) {
|
||||
|
Loading…
Reference in New Issue
Block a user