From 9d8b913465741479c17227564d539eb742f0f327 Mon Sep 17 00:00:00 2001 From: yanweidong Date: Wed, 2 Sep 2026 21:03:45 +0800 Subject: [PATCH] feat QMT_API.py --- api/qmt_rest_new.py | 121 +++++++---------- api/qmt_rest_rele.py | 123 ++++++------------ .../sdk/__pycache__/account.cpython-311.pyc | Bin 6063 -> 6063 bytes .../sdk/__pycache__/client.cpython-311.pyc | Bin 7033 -> 7033 bytes .../sdk/__pycache__/data.cpython-311.pyc | Bin 17201 -> 17201 bytes .../sdk/__pycache__/misc.cpython-311.pyc | Bin 6698 -> 6698 bytes .../sdk/__pycache__/trade.cpython-311.pyc | Bin 11929 -> 11926 bytes py-client/sdk/trade.py | 7 +- .../trend/__pycache__/open.cpython-311.pyc | Bin 6903 -> 6917 bytes .../trend/__pycache__/order.cpython-311.pyc | Bin 8219 -> 8250 bytes py-client/strategy/trend/boot.py | 1 - py-client/strategy/trend/open.py | 1 + py-client/strategy/trend/order.py | 1 + 13 files changed, 91 insertions(+), 163 deletions(-) diff --git a/api/qmt_rest_new.py b/api/qmt_rest_new.py index bedf133..fb705aa 100644 --- a/api/qmt_rest_new.py +++ b/api/qmt_rest_new.py @@ -26,10 +26,9 @@ def safe_call(func, *args, **kwargs): except HTTPError: raise except Exception as e: - logger.exception("%s call failed", func.__name__) raise HTTPError( - 502, - reason="QMT upstream call failed: %s" % func.__name__, + 500, + reason="QMT: %s call failed." % func.__name__, ) from e @@ -48,16 +47,13 @@ class BaseHandler(RequestHandler): if self.__class__ not in AUTH_EXEMPT: token = self.request.headers.get('X-Token') if token != TOKEN: - raise HTTPError(401, "Authentication failed: invalid or missing token") + raise HTTPError(500, "Authentication failed: invalid or missing token") def set_default_headers(self): self.set_header("Content-Type", "application/json; charset=utf-8") - def write_error(self, status_code, **kwargs): - self.finish(json.dumps({ - "error": self._reason, - "status_code": status_code - }, separators=(',', ':'), ensure_ascii=False)) + def write_error(self, **kwargs): + self.finish(self._reason) def ctx(self): return self.application.ContextInfo @@ -67,6 +63,7 @@ class BaseHandler(RequestHandler): # ============= 1. ContextInfo properties ============= +# "/api/v2/context/info" class ContextInfoHandler(BaseHandler): def get(self): ctx = self.ctx() @@ -80,38 +77,47 @@ class ContextInfoHandler(BaseHandler): "do_back_test": ctx.do_back_test, "benchmark": ctx.benchmark, "capital": ctx.capital, + "timetag":ctx.timetag, "universe": ctx.get_universe(), } self.write(data, separators=(',', ':'), ensure_ascii=False) - - # ============= 2. Data queries (ContextInfo get_*) ============= -# ContextInfo.get_stock_name() - Get a stock name by symbol -class StockNameHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(self.ctx().get_stock_name, stockcode) - self.write(json.dumps({"stockcode": stockcode, "name": ret}, separators=(',', ':'), ensure_ascii=False)) - -# get_open_date() - Get the listing date by symbol -class OpenDateHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(get_open_date, stockcode) - self.write(json.dumps({"stockcode": stockcode, "open_date": ret}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.get_last_volume() - Get the latest outstanding shares -class LastVolumeHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(self.ctx().get_last_volume, stockcode) - if ret is None: - raise HTTPError(500, "Failed to get outstanding shares") - self.write(json.dumps({"stockcode": stockcode, "last_volume": ret}, separators=(',', ':'), ensure_ascii=False)) +STOCK_HANDLER = { + # stock_name|open_date|last_volume|total_share|svol|bvol + "stock_name": ("get_stock_name", "stock_code", True), + "open_date": ("get_open_date", "stock_code", True), + "last_volume": ("get_last_volume", "stock_code", True), + "total_share": ("get_total_share", "stock_code", True), + "svol": ("get_svol", "stock_code", True), + "bvol": ("get_bvol", "stock_code", True), +} +# "/api/v2/get/*" ContextInfo.* Get a stock name by symbol +class StockGetHandler(BaseHandler): + def get(self,handler_type): + # 快速路径:配置查找 + cfg = STOCK_HANDLER.get(handler_type) + if not cfg: + self.write_error(500, reason="Unknown API") + return + + # 参数验证 + + query_vals = self.get_query_argument(cfg.index[1], "").strip() + if not query_vals: + self.write_error(500, reason=f"{cfg.index[1]} required") + return + + # 方法调用 + method = getattr(self.ctx(), cfg.index[0]) + result = safe_call(method, query_vals) + + + # 响应 + self.finish({ + "stock_code": query_vals, + "ref": result + }) # ContextInfo.get_bar_timetag() - Get the bar timestamp class BarTimetagHandler(BaseHandler): @@ -121,12 +127,6 @@ class BarTimetagHandler(BaseHandler): ret = safe_call(self.ctx().get_bar_timetag, index) self.write(json.dumps({"index": index, "timetag": ret}, separators=(',', ':'), ensure_ascii=False)) -# ContextInfo.get_tick_timetag() - Get the latest tick timestamp -class TickTimetagHandler(BaseHandler): - def get(self): - ret = safe_call(self.ctx().get_tick_timetag) - self.write(json.dumps({"timetag": ret}, separators=(',', ':'), ensure_ascii=False)) - # ContextInfo.get_sector() - Get index constituents class SectorHandler(BaseHandler): def post(self): @@ -285,14 +285,6 @@ class TimetagToDatetimeHandler(BaseHandler): ret = safe_call(timetag_to_datetime, timetag, fmt) self.write(json.dumps({"timetag": timetag, "datetime": ret}, separators=(',', ':'), ensure_ascii=False)) -# ContextInfo.get_total_share() - Get total shares -class TotalShareHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(self.ctx().get_total_share, stockcode) - self.write(json.dumps({"stockcode": stockcode, "total_share": ret}, separators=(',', ':'), ensure_ascii=False)) - # ContextInfo.get_trading_dates() - Get the trading-day list class TradingDatesHandler(BaseHandler): def post(self): @@ -306,22 +298,6 @@ class TradingDatesHandler(BaseHandler): ret = safe_call(self.ctx().get_trading_dates, stockcode, start_date, end_date, count_int, period) self.write(json.dumps({"dates": ret or []}, separators=(',', ':'), ensure_ascii=False)) -# ContextInfo.get_svol() - Get sell-side volume -class SvolHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(self.ctx().get_svol, stockcode) - self.write(json.dumps({"stockcode": stockcode, "svol": ret}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.get_bvol() - Get buy-side volume -class BvolHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - stockcode = data.get('stockcode', '') - ret = safe_call(self.ctx().get_bvol, stockcode) - self.write(json.dumps({"stockcode": stockcode, "bvol": ret}, separators=(',', ':'), ensure_ascii=False)) - # ContextInfo.get_longhubang() - Get Dragon-Tiger List data class LonghubangHandler(BaseHandler): def post(self): @@ -1272,6 +1248,9 @@ def make_app(): # V2 (r"/api/v2/positions", HoldingHandler), (r"/api/v2/assets", AssetsHandler), + # ContextInfo properties + (r"/api/v2/context/info", ContextInfoHandler), + (r"/api/v2/get/(stock_name|open_date|last_volume|total_share|svol|bvol)", StockGetHandler), # Legacy compatibility routes (r"/api/holding", HoldingHandler), @@ -1283,15 +1262,8 @@ def make_app(): (r"/api/order/cancel_by_id", CancelByIdHandler), (r"/api/order/deal", DealHandler), - # ContextInfo properties - (r"/api/context/info", ContextInfoHandler), - # Data queries - (r"/api/data/stock_name", StockNameHandler), - (r"/api/data/open_date", OpenDateHandler), - (r"/api/data/last_volume", LastVolumeHandler), (r"/api/data/bar_timetag", BarTimetagHandler), - (r"/api/data/tick_timetag", TickTimetagHandler), (r"/api/data/sector", SectorHandler), (r"/api/data/industry", IndustryHandler), (r"/api/data/stock_list_in_sector", StockListInSectorHandler), @@ -1306,10 +1278,7 @@ def make_app(): (r"/api/data/divid_factors", DividFactorsHandler), (r"/api/data/main_contract", MainContractHandler), (r"/api/data/timetag_to_datetime", TimetagToDatetimeHandler), - (r"/api/data/total_share", TotalShareHandler), (r"/api/data/trading_dates", TradingDatesHandler), - (r"/api/data/svol", SvolHandler), - (r"/api/data/bvol", BvolHandler), (r"/api/data/longhubang", LonghubangHandler), (r"/api/data/top10_share_holder", Top10ShareHolderHandler), (r"/api/data/option_detail", OptionDetailHandler), diff --git a/api/qmt_rest_rele.py b/api/qmt_rest_rele.py index 0f14d60..bedf133 100644 --- a/api/qmt_rest_rele.py +++ b/api/qmt_rest_rele.py @@ -67,55 +67,23 @@ class BaseHandler(RequestHandler): # ============= 1. ContextInfo properties ============= -# ContextInfo.period - Get the current period -class ContextPeriodHandler(BaseHandler): +class ContextInfoHandler(BaseHandler): def get(self): - self.write(json.dumps({"period": self.ctx().period}, separators=(',', ':'), ensure_ascii=False)) + ctx = self.ctx() + data = { + "period": ctx.period, + "barpos": ctx.barpos, + "time_tick_size": ctx.time_tick_size, + "stockcode": ctx.stockcode, + "dividend_type": ctx.dividend_type, + "market": ctx.market, + "do_back_test": ctx.do_back_test, + "benchmark": ctx.benchmark, + "capital": ctx.capital, + "universe": ctx.get_universe(), + } + self.write(data, separators=(',', ':'), ensure_ascii=False) -# ContextInfo.barpos - Get the current bar index -class ContextBarposHandler(BaseHandler): - def get(self): - self.write(json.dumps({"barpos": self.ctx().barpos}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.time_tick_size - Get the current bar count -class ContextTimeTickSizeHandler(BaseHandler): - def get(self): - self.write(json.dumps({"time_tick_size": self.ctx().time_tick_size}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.stockcode - Get the current chart symbol -class ContextStockCodeHandler(BaseHandler): - def get(self): - self.write(json.dumps({"stockcode": self.ctx().stockcode}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.dividend_type - Get the current adjustment mode -class ContextDividendTypeHandler(BaseHandler): - def get(self): - self.write(json.dumps({"dividend_type": self.ctx().dividend_type}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.market - Get the current chart market -class ContextMarketHandler(BaseHandler): - def get(self): - self.write(json.dumps({"market": self.ctx().market}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.do_back_test - Check whether backtesting is enabled -class ContextDoBackTestHandler(BaseHandler): - def get(self): - self.write(json.dumps({"do_back_test": self.ctx().do_back_test}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.benchmark - Get the backtest benchmark -class ContextBenchmarkHandler(BaseHandler): - def get(self): - self.write(json.dumps({"benchmark": self.ctx().benchmark}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.capital - Get the initial backtest capital -class ContextCapitalHandler(BaseHandler): - def get(self): - self.write(json.dumps({"capital": self.ctx().capital}, separators=(',', ':'), ensure_ascii=False)) - -# ContextInfo.get_universe() - Get symbols in the universe -class ContextUniverseHandler(BaseHandler): - def get(self): - self.write(json.dumps({"universe": self.ctx().get_universe()}, separators=(',', ':'), ensure_ascii=False)) # ============= 2. Data queries (ContextInfo get_*) ============= @@ -966,7 +934,8 @@ class TradeDetailDataHandler(BaseHandler): ret = safe_call(get_trade_detail_data, self.acc(), account, datatype) if ret is None: ret = [] - self.write(json.dumps({"data": ret}, separators=(',', ':'), ensure_ascii=False)) + result = [fixed_fields(obj) for obj in ret] + self.write(json.dumps({"data": result}, separators=(',', ':'), ensure_ascii=False)) # get_value_by_order_id() - Get order or trade details by order ID class ValueByOrderIdHandler(BaseHandler): @@ -1112,7 +1081,28 @@ class HoldingHandler(BaseHandler): data = json.loads(self.request.body) account = data.get('account', 'stock') positions = safe_call(get_trade_detail_data, self.acc(), account, 'position') or [] - self.write(json.dumps({"data": positions}, separators=(',', ':'), ensure_ascii=False)) + holding = {} + for position in positions: + stock = position.m_strInstrumentID + '.' + position.m_strExchangeID + holding[stock] = { + 'StockCode': stock, + 'StockName': position.m_strInstrumentName, + 'Direction': position.m_nDirection, + 'Volume': position.m_nVolume, + 'OpenPrice': position.m_dOpenPrice, + 'FloatProfit': position.m_dFloatProfit, + 'MarketValue': position.m_dMarketValue, + 'StockHolder': position.m_strStockHolder, + 'FrozenVolume': position.m_nFrozenVolume, + 'CanUseVolume': position.m_nCanUseVolume, + 'OnRoadVolume': position.m_nOnRoadVolume, + 'YesterdayVolume': position.m_nYesterdayVolume, + 'LastPrice': position.m_dLastPrice, + 'ProfitRate': position.m_dProfitRate, + 'FutureTradeType': position.m_eFutureTradeType, + 'ExpireDate': position.m_strExpireDate + } + self.write(json.dumps({"data": holding}, separators=(',', ':'), ensure_ascii=False)) # get_trade_detail_data('account') - Query account assets class AssetsHandler(BaseHandler): @@ -1126,28 +1116,6 @@ class AssetsHandler(BaseHandler): self.write(json.dumps({"total": round(info.m_dBalance, 2),"available": round(info.m_dAvailable, 2)}, separators=(',', ':'), ensure_ascii=False)) -# get_trade_detail_data('account') - Query total assets -class TotalMoneyHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - account = data.get('account', 'stock') - _data = safe_call(get_trade_detail_data, self.acc(), account, 'account') - info = _data[0] if _data else None - if not info: - raise HTTPError(500, "Failed to get account data") - self.write(json.dumps({"total_money": round(info.m_dBalance, 2)}, separators=(',', ':'), ensure_ascii=False)) - -# get_trade_detail_data('account') - Query available cash -class AvailableMoneyHandler(BaseHandler): - def post(self): - data = json.loads(self.request.body) - account = data.get('account', 'stock') - _data = safe_call(get_trade_detail_data, self.acc(), account, 'account') - info = _data[0] if _data else None - if not info: - raise HTTPError(500, "Failed to get account data") - self.write(json.dumps({"available_money": round(info.m_dAvailable, 2)}, separators=(',', ':'), ensure_ascii=False)) - # passorder(23) - Simplified buy order wrapper class BuyHandler(BaseHandler): def post(self): @@ -1307,8 +1275,6 @@ def make_app(): # Legacy compatibility routes (r"/api/holding", HoldingHandler), - (r"/api/money/total", TotalMoneyHandler), - (r"/api/money/available", AvailableMoneyHandler), (r"/api/order/buy", BuyHandler), (r"/api/order/sell", SellHandler), (r"/api/order/status", OrderStatusHandler), @@ -1318,16 +1284,7 @@ def make_app(): (r"/api/order/deal", DealHandler), # ContextInfo properties - (r"/api/context/period", ContextPeriodHandler), - (r"/api/context/barpos", ContextBarposHandler), - (r"/api/context/time_tick_size", ContextTimeTickSizeHandler), - (r"/api/context/stockcode", ContextStockCodeHandler), - (r"/api/context/dividend_type", ContextDividendTypeHandler), - (r"/api/context/market", ContextMarketHandler), - (r"/api/context/do_back_test", ContextDoBackTestHandler), - (r"/api/context/benchmark", ContextBenchmarkHandler), - (r"/api/context/capital", ContextCapitalHandler), - (r"/api/context/universe", ContextUniverseHandler), + (r"/api/context/info", ContextInfoHandler), # Data queries (r"/api/data/stock_name", StockNameHandler), diff --git a/py-client/sdk/__pycache__/account.cpython-311.pyc b/py-client/sdk/__pycache__/account.cpython-311.pyc index e2aaf11da61fee39611e4067c25665ae893c2ebb..a32c7d0bd187dfbd11d20fe1edd3512d37a4096f 100644 GIT binary patch delta 23 fcmZ3lzh0kjIWI340|Ns?&W34OtehM97K#G^OMC`5 delta 23 fcmZ3lzh0kjIWI340|Ns?-K$Ai_c=E5Effa;Q!xiv diff --git a/py-client/sdk/__pycache__/client.cpython-311.pyc b/py-client/sdk/__pycache__/client.cpython-311.pyc index 34ba3db988574938e475e5553132a4760831b815..96d91369c98f7cd1ebe6304a6f886167918aa5c1 100644 GIT binary patch delta 22 ecmexq_S1}aIWI340|Ns?&W34OOE&W6NCN;?bO$^D delta 22 dcmexq_S1}aIWI340|NttK;)z>yN$d#(g03o1|I+b diff --git a/py-client/sdk/__pycache__/data.cpython-311.pyc b/py-client/sdk/__pycache__/data.cpython-311.pyc index bc6d313669e3ce3c4e6c535f0cf90f3daedb1d99..4c6b9822952d12098e225f7770f07595e5a20b74 100644 GIT binary patch delta 24 fcmdnk#<;PKk#{*SFBby?14GV+X<3OIc~zVNSv>~p delta 24 gcmdnk#<;PKk#{*SFBby?1H+5k6SDX=@~Suk09_~tIRF3v diff --git a/py-client/sdk/__pycache__/misc.cpython-311.pyc b/py-client/sdk/__pycache__/misc.cpython-311.pyc index 7ce8e3c4ba0864589bb58864441f47f8a4e63550..9afa90a0f266aade06e279f93b1d31da5e622a10 100644 GIT binary patch delta 22 ecmZ2wvdV;aIWI340|Ns?&W34O3peu0N&x^!fCfhZ delta 22 ecmZ2wvdV;aIWI340|NuYi`x^jnl|#vN&x^(ZwAQ# diff --git a/py-client/sdk/__pycache__/trade.cpython-311.pyc b/py-client/sdk/__pycache__/trade.cpython-311.pyc index 3871555c828b786eed3022403809498ac312eaa0..035a006fb166e63caed6e7d053227a5c4a93472b 100644 GIT binary patch delta 1408 zcmZ{jdu&s66vxlGUGMtb`eMB^bkBBO%c!hu6(=r~fn^Nbz=2X(O6{FVrR&V?7;a-> zz9z3s*&&dPGBw7*G9w$E#6Yr;XoAs1|CEeG{_>CgrHOwSO-#(WwGMnV=_kG4^X>PZ zd+zy7^<3;JxoS2W006e1zVwQ-?0kuI@*n_Q0vTjXK{v>PtVv;?5ET&QqNqmJMvG+e zum&Kijf&A?xmebzUwyVHsuLgrvf(X|jk5y4yuiu)iRxw3bKoebr438Y9RM)*u*ufMH9w5|?}TCSOaY1F?a4=4gl(%Vy17n-lWmKTfi<37?=T=P_}Z z(?-Z41#t^Sq``vlh14WI$+c1XL&{=HZo2#@0o&-z`ss!VewD(CsjEMe97y)3+Xs64 zl=s+t9sn}DV^vj(pM?w5HMY-*Nj1d~GI4+*yf1ah^D|X>i zxwgs~3m(BVKhn=3pU1#x~ci63#m4;SBJ4Zcc9vcc#7gR_N^bQUFSWV@<^Z8 zcy!W3qf5mz1F?QZ?p0z*d3SE1MvJw7cd=qf#M7}vJe}xGDV$rFY>4jFwqgf4-485k zA8L1l+|fLVo)GS#r#i?-&(c?QZ~V96 zCLQs5u#?8UQ#OSYctk!SKcX3GtasrJ>Z~uvE=ty4#j|Afwc|c|(Kl^mr*d1p>!d%7 z`)RvBg_r5N-+i)$)vXLZy~<9;F2){4Cu2Y30OJrN#(0VGG9$@IF3o9WA(HyF|Z03QB+ap10bD${!EWdOJgGRPQ&9*_lD6U0HmBOu5ry#jzo z<4KXVy&3?I)+2gSWl>K2(`HjVX#(s9SvLW4`kVl;D6lvGJUUr_0HlmH1ON%+=vrf0 z!nnpA8kU4L3jnNH0hT_rYcM1Bjb=BZk@VV|+O_rd^>w5J?- ztfb$vucC*}Z|TG;THP`%_HpnvsxTGPuyH$9)1q-?L+sH##c>$`=m(>lzBB2Q!Jkbn zxSh7T~K5F9jPt`VPRixB;2{up1O(cFAX6aY?U_b5I&(A|HcKUC$7 z`XWc_=tl0Gfny6oV%8_5^qg9AT4D%C^>E1HE89mK1JVYjw|X>>cj$fpahI z$?L?%*mT}Q0e8}wtygf8?6w@s6d$_CYrvaTSg5#IxI|sHI^0F$wpx6T#-totv2|5U z@+gJ4=#E4J(MVkPh7un1%KiT6{~5H=@V4XPd3L-&e{O5X9kJ$ut5~C6{TR!M7++4K z6tZAsT;oET#BCeYW0YlgV|#4BU5_>I0zljl^hKiHup$Q(Z@;X}sjVe4*z<|oEYSN! zHtdL9FVbT1m1Mh&(vGgTUvs9X}omC7-4T7r6eRqd5tQ|Y#5`?vOIi|0%h}ffecay?xUBaD|$Yu ze5Lk7k0dwlrzTerXKB&pIQ1;c&olTNSK1gIjBdt0#sS75hKF&O;b*+b7+?%C-eU0f zDsMB!7!!=MjE@-ej0MIG#wSn&piWbrjB<;`7~?kMYsMrUEw`X9cCNfs(ATn3$Ec^} u%7S8EQ>B8zyZl$$bAw@dC>Ur`Rset>EHXupDoaz1*0HS9;yEg>I`TKvMrS1e diff --git a/py-client/sdk/trade.py b/py-client/sdk/trade.py index af19abd..7eec68e 100644 --- a/py-client/sdk/trade.py +++ b/py-client/sdk/trade.py @@ -1,7 +1,8 @@ from .models import * from typing import Any -OP_BUY, OP_SELL = 23, 24 +OP_BUY = 23 +OP_SELL = 24 ORDER_TYPE_VOLUME, PR_TYPE_LATEST, QUICK_TRADE_NOW = 1101, 5, 2 ORDER_SIDE_BY_OFFSET = {"23": "BUY", "24": "SELL", "48": "BUY", "49": "SELL"} @@ -16,11 +17,11 @@ class TradeMixin: return self._post("/api/trade/passorder", body) def passorder_latest(self, side, stock, volume): return self.passorder_latest_tagged(side, stock, volume, "", "") - def passorder_latest_tagged(self, side, stock, volume, strategy_name, order_id): + def passorder_latest_tagged(self, side, stock_code, volume, strategy_name, order_id): body = { "opType": side, "orderType": ORDER_TYPE_VOLUME, - "stock": stock, + "stockCode": stock_code, "prType": PR_TYPE_LATEST, "price": -1, "volume": volume, diff --git a/py-client/strategy/trend/__pycache__/open.cpython-311.pyc b/py-client/strategy/trend/__pycache__/open.cpython-311.pyc index f90d40f67cbc13f9c9cd5a456447598dc2381b1b..4eb46795f5ee36047758b974d6f06b217e1d9db6 100644 GIT binary patch delta 173 zcmexv+G@tToR^o2fq{XcvU_^g%8k5x`M5Y47#Nrt7#KgFntX*Xo-c)|hN*_7hItt~ z1H)?e$@cu-;>^n!85mYGg0z7^6JrWXFoP!RjIt`yLc;J(4Z zcY{OV28Yl`ehz-NFAN;~Yz^)ogf{OG_`}Q?ym_mL6EkDs<{#o4nM8OQ4L>lT5(<;| HN?8E_el;wx delta 171 zcmZoQ`)+B*MdJ_<;eH Kkehs3$_fCJj4b2; diff --git a/py-client/strategy/trend/__pycache__/order.cpython-311.pyc b/py-client/strategy/trend/__pycache__/order.cpython-311.pyc index f6692ab815b649ab8acbca8219a30586b3f81833..fa69a5b7c09a313a469a9cdef875f3d61e566ad6 100644 GIT binary patch delta 1113 zcmZWnOHUI~6u#4$P9O9EK4^(N%A?qcyb2M}@DQ+)XrV}pMj|QA%%xPOkDO@}B^q$0 zap{e^Fs{|5c7+S|M-Ud>xp3hQqEX|*m~)2$>MXu|^PPLY^SI~vg?AU+FWqh@A%t{4 ze0J;e8~1=kSY#8H{%$*!G{*=bM3bnbIXRQ5q}3cS7iaD`Q9SIa1zgq@J)bI8tOdxZ zOcvh?i)>5mx7BV&H>3BX?28x_Ld+|Dv_cahq`V{53AMu6xJiR3PCm}Ul&5`mHf$d9>W5LL19m9iqOSA*an3V`)=FmA0>p$Di#<*&p|?n zBEc~7MubU1NJU(ucMQq2M~mO~1|eMbJ31v{gpIqWg;Dmv{aWZ{VNd4(zaggz1)9?; z?#YGtjbuDAkywaF;%1Js)kGChr#Zz5!|ahqi5<#zHI-ATPPK}ZDbg%NuzZ|*;NSxV z>#_k|0cxzS*Tq1iFqzM<_3TSSWsCQ{?L?FxGfJvT4Py)^1j}r@9)_;|-JuLLn}RjK z^Dv9hf;T;SUQOxAJh~?{8jP}gK6VmA(25X1a3IXHpg+BF87Utm?EfQA$ E2R6s^-T(jq delta 1059 zcmZXSOHUI~6oBvT4AW_8!51w=fvLqdBU&mb)zA@;=d!nkv7LX7Fc#D4%mH?GW?v4A>@FK5pCoO|BSJevu>4u^w;5R!ME zKG=F2p77BEpY@H$MJAeZmJnh}Of&;~QqYyUi$o3amp9Dxv`C<-KbUW(BXZcDdlf`5{}hc2O+ zq8XC>onNJ+{F{H0CU~FxWgNR$RDCdsIWG`GR1q>LpFqqKLfXPQd*p~-dQ34G7@+A^ zCXf*66kiQ5&@6uy-lQpB=t)et5t3f7vzpls&#e@1YsJ!RX{DGedNs~>3bh4`)zlzl z_-2nfwy%~Ay=E|rnQgJsU{#pM_Hnh!-Umredxz;{E7tqLf9x7I>35oj!5n8A_W&B- zjX{ZDDOiP3?qgR0mL$&?=Np$LD5~8 z+j9|r-E3D;!WF^|+@tL6@h;YofH_U8(H7W416I++-IE`;RH>D{8RY{rLK4He>XvS> z$GuC~+njB$r|Ood8%%4Z2JQ(Pr!mne){?x#a8CrU!IQ>NN_%gLM*znWt`;R#@*dgM zVm}A$b6!+GYP3aVp>lZZItB90Mq8hWE*R9WM`ZNd!dbBH?# zK%7D(5I8re9mIHb@WnaTfI4-+&DsuX+FG;G1g2@=zV|ei@mqGejN4r1Q$sfwN~k+> zc`0AGo-5_%_s{S;W?w`^J9YkP;Fp}O+Gf*Y)9{3U9okLHG`dax#}4X#Aa(@e8`+}q UZ6A6?I8`EiOp$n085Xhq-{~ab6#xJL diff --git a/py-client/strategy/trend/boot.py b/py-client/strategy/trend/boot.py index bc3df77..7f276b9 100644 --- a/py-client/strategy/trend/boot.py +++ b/py-client/strategy/trend/boot.py @@ -108,7 +108,6 @@ def StartTrend() -> None: def RunOnce(run: Runtime, signals:list[SignalItem]) -> None: """按固定步骤执行一轮趋势策略, ``RunOnce``。""" if not trading_time(datetime.now()): - log.info("[运行] 非交易时间,跳过本轮") return print("=" * 40 + f" Ticker {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} " +"=" * 40) diff --git a/py-client/strategy/trend/open.py b/py-client/strategy/trend/open.py index bfbdddb..d5bf07a 100644 --- a/py-client/strategy/trend/open.py +++ b/py-client/strategy/trend/open.py @@ -71,6 +71,7 @@ def do_open(run:Runtime,code:str,volume:int,signal_key:str)->None: run.client, OP_BUY, code, + -1, volume, order_id, signal_key, diff --git a/py-client/strategy/trend/order.py b/py-client/strategy/trend/order.py index 59fc0db..51785f4 100644 --- a/py-client/strategy/trend/order.py +++ b/py-client/strategy/trend/order.py @@ -25,6 +25,7 @@ class PlaceOrderRequest: client: Any op: int code: str + price: float volume: int order_id: str strategy_name: str