From cad31ccc53d7f2809036fa7c5ec9e4d505487213 Mon Sep 17 00:00:00 2001 From: fasiondog Date: Thu, 30 Jun 2022 00:51:09 +0800 Subject: [PATCH] =?UTF-8?q?fixed=20https://gitee.com/fasiondog/hikyuu/issu?= =?UTF-8?q?es/I5EJ0I=20=E8=AE=A2=E5=8D=95=E4=BB=A3=E7=90=86=E5=A4=B1?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/source/trade_manage/OrderBroker.rst | 7 +- .../examples/notebook/006-TradeManager.ipynb | 98 +++++++++++++++---- hikyuu/trade_manage/broker.py | 34 ++----- hikyuu_cpp/hikyuu/Stock.h | 2 +- .../hikyuu/trade_manage/TradeManager.cpp | 6 +- .../hikyuu/trade_manage/TradeManagerBase.h | 1 - 6 files changed, 90 insertions(+), 58 deletions(-) diff --git a/docs/source/trade_manage/OrderBroker.rst b/docs/source/trade_manage/OrderBroker.rst index 847a03e3e..a571c0b70 100644 --- a/docs/source/trade_manage/OrderBroker.rst +++ b/docs/source/trade_manage/OrderBroker.rst @@ -18,12 +18,11 @@ Python中的订单代理包装 my_tm = crtTM(init_cash = 300000) #注册实盘交易订单代理 - my_tm.regBroker(crtOB(TestOrderBroker())) #TestOerderBroker是测试用订单代理对象,只打印 - #my_tm.regBroker(crtOB(Puppet())) #Puppet为内建的扯线木偶实盘下单对象 - #my_tm.regBroker(crtOB(MailOrderBroker("smtp.sina.com", "yourmail@sina.com", "yourpwd", "receivermail@XXX.yy))) + my_tm.reg_broker(crtOB(TestOrderBroker())) #TestOerderBroker是测试用订单代理对象,只打印 + #my_tm.reg_broker(crtOB(MailOrderBroker("smtp.sina.com", "yourmail@sina.com", "yourpwd", "receivermail@XXX.yy))) #根据需要修改订单代理最后的时间戳,后续只有大于该时间戳时,订单代理才会实际发出订单指令 - my_tm.brokeLastDatetime=Datetime(201706010000) + my_tm.broke_last_datetime=Datetime(201706010000) #创建信号指示器(以5日EMA为快线,5日EMA自身的10日EMA作为慢线,快线向上穿越慢线时买入,反之卖出) my_sg = SG_Flex(OP(EMA(n=5)), slow_n=10) diff --git a/hikyuu/examples/notebook/006-TradeManager.ipynb b/hikyuu/examples/notebook/006-TradeManager.ipynb index 616cf065f..35030bfb1 100644 --- a/hikyuu/examples/notebook/006-TradeManager.ipynb +++ b/hikyuu/examples/notebook/006-TradeManager.ipynb @@ -11,15 +11,17 @@ "text": [ "std::cout are redirected to python::stdout\n", "std::cerr are redirected to python::stderr\n", - "2021-02-12 17:02:02.409 [HKU-I] - Using SQLITE3 BaseInfoDriver (BaseInfoDriver.cpp:58)\n", - "2021-02-12 17:02:02.411 [HKU-I] - Loading market information... (StockManager.cpp:473)\n", - "2021-02-12 17:02:02.412 [HKU-I] - Loading stock type information... (StockManager.cpp:486)\n", - "2021-02-12 17:02:02.413 [HKU-I] - Loading stock information... (StockManager.cpp:422)\n", - "2021-02-12 17:02:02.501 [HKU-I] - Loading stock weight... (StockManager.cpp:503)\n", - "2021-02-12 17:02:03.904 [HKU-I] - Loading KData... (StockManager.cpp:138)\n", - "2021-02-12 17:02:03.909 [HKU-I] - Preloading all day kdata to buffer! (StockManager.cpp:161)\n", - "2021-02-12 17:02:03.931 [HKU-I] - 0.03s Loaded Data. (StockManager.cpp:149)\n", - "Wall time: 2.78 s\n" + "2022-06-30 00:49:42.300 [HKU-I] - Using SQLITE3 BaseInfoDriver (BaseInfoDriver.cpp:58)\n", + "2022-06-30 00:49:42.301 [HKU-I] - Loading market information... (StockManager.cpp:497)\n", + "2022-06-30 00:49:42.301 [HKU-I] - Loading stock type information... (StockManager.cpp:510)\n", + "2022-06-30 00:49:42.301 [HKU-I] - Loading stock information... (StockManager.cpp:424)\n", + "2022-06-30 00:49:42.348 [HKU-I] - Loading stock weight... (StockManager.cpp:527)\n", + "2022-06-30 00:49:42.714 [HKU-I] - Loading KData... (StockManager.cpp:139)\n", + "2022-06-30 00:49:42.717 [HKU-I] - Preloading all day kdata to buffer! (StockManager.cpp:162)\n", + "2022-06-30 00:49:42.717 [HKU-I] - Preloading all week kdata to buffer! (StockManager.cpp:165)\n", + "2022-06-30 00:49:42.717 [HKU-I] - Preloading all month kdata to buffer! (StockManager.cpp:168)\n", + "2022-06-30 00:49:42.729 [HKU-I] - 0.01s Loaded Data. (StockManager.cpp:150)\n", + "Wall time: 1.08 s\n" ] } ], @@ -56,7 +58,7 @@ "output_type": "stream", "text": [ "TradeManager {\n", - " params: params[precision(int): 2, reinvest(bool): 0, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n", + " params: params[precision(int): 2, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n", " name: SYS,\n", " init_date: 2017-01-01 00:00:00,\n", " init_cash: 100000.00,\n", @@ -71,7 +73,7 @@ " current borrow_cash: 0.00,\n", " current borrow_asset: 0.00,\n", " Position: \n", - " SZ000001 平安银行 2017-01-03 00:00:00 999 100.00 911.00 2493.00 1582.00 173.66% 1.58%\n", + " SZ000001 平安银行 2017-01-03 00:00:00 1333 100.00 911.00 1464.00 553.00 60.70% 0.55%\n", " Short Position: \n", " Borrow Stock: \n", "}\n" @@ -141,21 +143,21 @@ " SZ000001\n", " 平安银行\n", " 2017-01-03\n", - " 999\n", + " 1333\n", " 100\n", " 911.0\n", - " 2493.0\n", - " 1582.0\n", - " 173.655324\n", + " 1464.0\n", + " 553.0\n", + " 60.702525\n", " \n", " \n", "\n", "" ], "text/plain": [ - " 证券名称 买入日期 已持仓天数 持仓数量 投入金额 当前市值 盈亏金额 盈亏比例\n", - "证券代码 \n", - "SZ000001 平安银行 2017-01-03 999 100 911.0 2493.0 1582.0 173.655324" + " 证券名称 买入日期 已持仓天数 持仓数量 投入金额 当前市值 盈亏金额 盈亏比例\n", + "证券代码 \n", + "SZ000001 平安银行 2017-01-03 1333 100 911.0 1464.0 553.0 60.702525" ] }, "execution_count": 3, @@ -178,7 +180,7 @@ "data": { "text/plain": [ "TradeManager {\n", - " params: params[precision(int): 2, reinvest(bool): 0, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n", + " params: params[precision(int): 2, save_action(bool): 1, support_borrow_cash(bool): 0, support_borrow_stock(bool): 0, ],\n", " name: SYS,\n", " init_date: 2017-01-01 00:00:00,\n", " init_cash: 100000.00,\n", @@ -282,6 +284,60 @@ "" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 4 使用订单代理" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "买入:SZ000001 18.300 1000\n", + "卖出:SZ000001 17.510 1000\n", + "买入:SZ000001 17.410 1000\n", + "卖出:SZ000001 17.000 1000\n", + "买入:SZ000001 17.340 1000\n", + "卖出:SZ000001 16.500 1000\n", + "买入:SZ000001 17.030 1000\n", + "卖出:SZ000001 16.350 1000\n", + "买入:SZ000001 15.110 1000\n", + "卖出:SZ000001 14.880 1000\n", + "买入:SZ000001 14.740 1000\n", + "卖出:SZ000001 14.090 1000\n", + "买入:SZ000001 14.470 1000\n" + ] + } + ], + "source": [ + "#创建模拟交易账户进行回测,初始资金30万\n", + "my_tm = crtTM(init_cash=300000, date=Datetime(201701010000))\n", + "\n", + "#注册实盘交易订单代理\n", + "my_tm.reg_broker(crtOB(TestOrderBroker(), False)) #TestOerderBroker是测试用订单代理对象,只打印\n", + "#my_tm.regBroker(crtOB(MailOrderBroker(\"smtp.sina.com\", \"yourmail@sina.com\", \"yourpwd\", \"receivermail@XXX.yy)))\n", + "\n", + "#根据需要修改订单代理最后的时间戳,后续只有大于该时间戳时,订单代理才会实际发出订单指令\n", + "my_tm.broker_last_datetime=Datetime(201701010000)\n", + "\n", + "#创建信号指示器(以5日EMA为快线,5日EMA自身的10日EMA作为慢线,快线向上穿越慢线时买入,反之卖出)\n", + "my_sg = SG_Flex(EMA(n=5), slow_n=10)\n", + "\n", + "#固定每次买入1000股\n", + "my_mm = MM_FixedCount(1000)\n", + "\n", + "#创建交易系统并运行\n", + "sys = SYS_Simple(tm = my_tm, sg = my_sg, mm = my_mm)\n", + "sys.run(sm['sz000001'], Query(-150))" + ] + }, { "cell_type": "code", "execution_count": null, @@ -292,7 +348,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -306,7 +362,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.3" + "version": "3.9.7" } }, "nbformat": 4, diff --git a/hikyuu/trade_manage/broker.py b/hikyuu/trade_manage/broker.py index 10f031ce4..af8187203 100644 --- a/hikyuu/trade_manage/broker.py +++ b/hikyuu/trade_manage/broker.py @@ -37,45 +37,26 @@ class OrderBrokerWrap(OrderBrokerBase): """订单代理包装类,用户可以参考自定义自己的订单代理,加入额外的处理 包装只有买卖操作参数只有(code, price, num)的交易接口类 """ - def __init__(self, broker, real=True, slip=0.03): + def __init__(self, broker, slip=0.03): """ 订单代理包装类,用户可以参考自定义自己的订单代理,加入额外的处理 - :param bool real: 下单前是否重新实时获取实时分笔数据 :param float slip: 如果当前的卖一价格和指示买入的价格绝对差值不超过slip则下单, 否则忽略; 对卖出操作无效,立即以当前价卖出 """ super(OrderBrokerWrap, self).__init__() self._broker = broker - self._real = real self._slip = slip def _buy(self, datetime, market, code, price, num): """实现 OrderBrokerBase 的 _buy 接口""" - if self._real: - import tushare as ts - df = ts.get_realtime_quotes(code) - new_price = float(df.ix[0]['ask']) - if (abs(new_price - price) <= self._slip): - self._broker.buy(code, new_price, num) - else: - print("out of slip, not buy!!!!!!!!!!") - return Datetime.now() - else: - self._broker.buy(code, price, num) - return datetime + self._broker.buy('{}{}'.format(market, code), price, num) + return datetime def _sell(self, datetime, market, code, price, num): """实现 OrderBrokerBase 的 _sell 接口""" - if self._real: - import tushare as ts - df = ts.get_realtime_quotes(code) - new_price = float(df.ix[0]['bid']) - self._broker.sell(code, new_price, num) - return Datetime.now() - else: - self._broker.sell(code, price, num) - return datetime + self._broker.sell('{}{}'.format(market, code), price, num) + return datetime class TestOrderBroker: @@ -90,13 +71,12 @@ def sell(self, code, price, num): print("卖出:%s %.3f %i" % (code, price, num)) -def crtOB(broker, real=True, slip=0.03): +def crtOB(broker, slip=0.03): """ 快速生成订单代理包装对象 :param broker: 订单代理示例,必须拥有buy和sell方法,并且参数为 code, price, num - :param bool real: 下单前是否重新实时获取实时分笔数据 :param float slip: 如果当前的卖一价格和指示买入的价格绝对差值不超过slip则下单, 否则忽略; 对卖出操作无效,立即以当前价卖出 """ - return OrderBrokerWrap(broker, real, slip) \ No newline at end of file + return OrderBrokerWrap(broker, slip) \ No newline at end of file diff --git a/hikyuu_cpp/hikyuu/Stock.h b/hikyuu_cpp/hikyuu/Stock.h index b49e447b6..6de23dacd 100644 --- a/hikyuu_cpp/hikyuu/Stock.h +++ b/hikyuu_cpp/hikyuu/Stock.h @@ -210,7 +210,7 @@ class HKU_API Stock { /** 是否为Null */ bool isNull() const; - /** (临时函数)只用于更新缓存中的日线数据 **/ + /** (临时函数)只用于更新缓存中的K线数据 **/ void realtimeUpdate(KRecord, KQuery::KType ktype = KQuery::DAY); /** 仅用于python的__str__ */ diff --git a/hikyuu_cpp/hikyuu/trade_manage/TradeManager.cpp b/hikyuu_cpp/hikyuu/trade_manage/TradeManager.cpp index 13234fc7a..282df0191 100644 --- a/hikyuu_cpp/hikyuu/trade_manage/TradeManager.cpp +++ b/hikyuu_cpp/hikyuu/trade_manage/TradeManager.cpp @@ -118,8 +118,6 @@ void TradeManager::_reset() { m_position.clear(); m_position_history.clear(); - // m_broker_list - // m_broker_last_datetime = Datetime::now(); m_actions.clear(); _saveAction(m_trade_list.back()); } @@ -867,7 +865,7 @@ TradeRecord TradeManager::buy(const Datetime& datetime, const Stock& stock, pric list::const_iterator broker_iter = m_broker_list.begin(); for (; broker_iter != m_broker_list.end(); ++broker_iter) { Datetime realtime = - (*broker_iter)->buy(datetime, stock.market(), stock.code(), planPrice, number); + (*broker_iter)->buy(datetime, stock.market(), stock.code(), realPrice, number); if (realtime != Null()) m_broker_last_datetime = realtime; } @@ -955,7 +953,7 @@ TradeRecord TradeManager::sell(const Datetime& datetime, const Stock& stock, pri list::const_iterator broker_iter = m_broker_list.begin(); for (; broker_iter != m_broker_list.end(); ++broker_iter) { Datetime realtime = - (*broker_iter)->sell(datetime, stock.market(), stock.code(), planPrice, number); + (*broker_iter)->sell(datetime, stock.market(), stock.code(), realPrice, real_number); m_broker_last_datetime = realtime; } } diff --git a/hikyuu_cpp/hikyuu/trade_manage/TradeManagerBase.h b/hikyuu_cpp/hikyuu/trade_manage/TradeManagerBase.h index 18e466dce..9e6f1adc9 100644 --- a/hikyuu_cpp/hikyuu/trade_manage/TradeManagerBase.h +++ b/hikyuu_cpp/hikyuu/trade_manage/TradeManagerBase.h @@ -158,7 +158,6 @@ class HKU_API TradeManagerBase { /** 复位,清空交易、持仓记录 */ void reset() { - m_broker_last_datetime = Datetime::now(); _reset(); }