From 6334f10904f8bb95d7e0b8321c8b6b13f694795f Mon Sep 17 00:00:00 2001 From: yanweidong Date: Sun, 30 Aug 2026 14:46:34 +0800 Subject: [PATCH] feat order.py --- api/qmt_api_new.py | 2 +- .../libs/__pycache__/calc.cpython-311.pyc | Bin 1850 -> 1850 bytes .../sdk/__pycache__/__init__.cpython-311.pyc | Bin 924 -> 1014 bytes .../sdk/__pycache__/account.cpython-311.pyc | Bin 5343 -> 6063 bytes .../sdk/__pycache__/models.cpython-311.pyc | Bin 9314 -> 16581 bytes .../sdk/__pycache__/trade.cpython-311.pyc | Bin 10499 -> 11929 bytes .../ipo/__pycache__/boot.cpython-311.pyc | Bin 2608 -> 2896 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 538 -> 167 bytes .../trend/__pycache__/boot.cpython-311.pyc | Bin 9281 -> 9682 bytes .../trend/__pycache__/open.cpython-311.pyc | Bin 4988 -> 5127 bytes .../trend/__pycache__/order.cpython-311.pyc | Bin 11407 -> 7459 bytes .../__pycache__/positions.cpython-311.pyc | Bin 8937 -> 8967 bytes .../trend/__pycache__/state.cpython-311.pyc | Bin 12180 -> 16385 bytes py-client/strategy/trend/boot.py | 10 +-- py-client/strategy/trend/order.py | 70 +++++++++--------- py-client/strategy/trend/state.py | 1 - .../__pycache__/test_ipo.cpython-311.pyc | Bin 0 -> 10574 bytes .../__pycache__/test_trend.cpython-311.pyc | Bin 13561 -> 20035 bytes py-client/tests/test_trend.py | 33 ++++++++- 19 files changed, 70 insertions(+), 46 deletions(-) create mode 100644 py-client/tests/__pycache__/test_ipo.cpython-311.pyc diff --git a/api/qmt_api_new.py b/api/qmt_api_new.py index 381fbda..46039f6 100644 --- a/api/qmt_api_new.py +++ b/api/qmt_api_new.py @@ -1123,7 +1123,7 @@ class AssetsHandler(BaseHandler): info = _data[0] if _data else None if not info: raise HTTPError(500, "Failed to get account data") - self.write(json.dumps({"data": info}, ensure_ascii=False)) + self.write(json.dumps({"total": round(info.m_dBalance, 2),"available": round(info.m_dAvailable, 2)}, ensure_ascii=False)) # get_trade_detail_data('account') - Query total assets diff --git a/py-client/libs/__pycache__/calc.cpython-311.pyc b/py-client/libs/__pycache__/calc.cpython-311.pyc index f7b26b821aaca11ef84238203ed41771e3a16e40..70a6308ef27f0327c742f895671ae2168accb200 100644 GIT binary patch delta 20 ccmdnRw~LQ^IWI340|NuY;;oZ5a_h4L065PDLjV8( delta 20 bcmdnRw~LQ^IWI340|NuYwb+Rpx%JrrI3EQa diff --git a/py-client/sdk/__pycache__/__init__.cpython-311.pyc b/py-client/sdk/__pycache__/__init__.cpython-311.pyc index 842d9ff5fb7ec023bcb3e0f8daf2412177cbb667..e79a499ba19c58ffeac03cc6a1ddedfc7b0a8d7f 100644 GIT binary patch delta 163 zcmbQk{*9e)IWI340|Ns?-K$AiQcN59IvEx8U94it^NX@$3QH67N@9{S({&4TOJWKt zb(3>4Q}aqD&t!CAOS&?DU|`^ekqzu1SR}x}zyJW5 C7&V6g delta 72 zcmeyyK8KxeIWI340|Ns?{p|@^*BCeQbuuyu>P_Cx=)%Y``43~r>yYqz`(!&0P;W*;Q#;t diff --git a/py-client/sdk/__pycache__/account.cpython-311.pyc b/py-client/sdk/__pycache__/account.cpython-311.pyc index 5596a6fcb32caaf77d4a7ad054e97ac68a80a3ff..e2aaf11da61fee39611e4067c25665ae893c2ebb 100644 GIT binary patch delta 2355 zcmaJ?ZA?>F7=F*aw;z18g%(;Uh*dsY0@V!^kupC(#X&W|rkesOZDEDdveS!>Sq4A0 zgc%n<&K8M@kz|QtTq0&!!cVuvgn!<<++^e?#QoTkWxr}%_G3Sm<-LVk7~Ad1(|gW& z&v~Es^S*FD_L?7TEeIVv-2$pHr-zNZ%$mZFQ4li8PBR_VWtDM#QRYM>cj8DZx zRR{&dKrkZ<07%pZ0Iv=Jz-<_XBn;SRh?pfamU&N-t-5Y<*BpKD5ZoL^Z>fbNG(IsT z(m*IY6bg%hNc16RQMtx_st^&w6A5%7`;!}=H32}P5&-5vD)Fbs)2h4WO6kEBK`!+v zrM}GiE2O!FGr!5X{59vC8ImMpn@&JxxqUzj0KiSu+=Lhpjt>Rnp)j@LVU3B)MT-G| z+5zC>diFE#U_E?Mof)|~)7)&W>9Hi-==kzXW=b7s$cNndx6&Fm%+Jxx4@H8ao2Teh zRX~-h?ouE+6;2>+*Un03EvVF;R_Yu~kM9pZZCWk9+oqK5U#?y$lFQnavi8ib#=&h+ zbwiW!gh+ExU2Y^1i6z89EErY=`H!3;l~-OQPaEB2^xht;ZDWG0A%B z>F~T^y|HD*@vKU2JgGFEl+69}qu0l;jxW?K*2-p&V)jU8&+55(em$@FM(}Qvoaa*V zTq)pkPLMS%4OT0q62DyHS4#ZzU2B^6mvbartK4R5Rcx&*U6QR+%I{pa*lryEeEQn- zhBtcO`KkB9kG&V<-T|d|KynVs&OyaFC|L$2;~;ggZeh5r4gek!T7{0rgx&~#Ek^RW zP(ljXZ^ABuvOT-=y@APy_k(ye6p4*e4<<={);UIXds{G%5*Xw;SP0#V--$29I}JNwU4+L|}%?v;+Vc(=!WK zBJ_bX)qjQg8pfVcmOZrS@5q>^-G;Pf3=u^Ovt*xq4;cz~VvK zQmNZKzm4};v(a-x)r~~s0WpiY#y2|_$aFsz zaLLhhkL!ti6p1y8aWN1bnuy23)1~ZdF^5stS{Y zVnd_{5n2!qq3zjK;mmWAGS-}TggDrxypiI=DCOHO^)j!VlrwWaN}b6ce|PJxs(zC8 zPfv#3M6=OtNc$gab0__(FdPp}Ck&glx!FwGSb?d8R4})xjX2nd=|S1+SpUmotj>IZ zRI(v+D{-(p<}3Esve}+t^_DtP#riFE#KC4P$wrO2<_hfIv@0uLGFw^sQd_W(RI~F1 z-5R6Mn5S@;{RAG&R)TXs8z^*;8a7pUh&b5e!ZWjbaTz}-6pL0XQQClSTB3UK?M(!X zJ8i~3#z$fzZO7>mgf@he2&WOc5&Q`FJ;yOYl2VGMoQpy zH4FL_@Vc69z@>7(+)mH4U{UqCItg|dDZPt~lN9WX NFSYeQ{$p2j&_DkjAb$V= delta 1710 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 GIsXnPr>nsL delta 2884 zcmaJ@O;A%;6uvJniI5N?LH-Q{!JnuDVx?8oj#NO}(MZLg3bpAo_X3e5FW&c1(T=gx z%ygzJ<`n9zCPhv2-%*dq;I@#kSD7_TZa9-7mm?UiLn)kVg`AO*^h zHWwMM0V!C96e%)Z3sO}X(v~9Qbs&Yxkm`$!H-J=KhSXSOya}Xm8B%kR@fMIammzH} zG9Cq~rVOdI$aveF9&L&6*eHu{`xj}BYfjL}dW6Y`KX(>|RON4jybk27C*UZdJR{XQ- z-SJIiOv82pW?tmfV&vgo$IA`dSgz*jls#_Qa&N3ZH+#wPB8o)EE(dn53R$>c`>nT7 zN6|*1XX8jVWguGjiWnyDr3oAFziN~=+q`LSq*aKgfz2Bl;LJ%HQ`+^ zZP=LgzK5|p3%@pvc)FgWqH&Fq9rwFFBd{9i8V|ZrK<`u!yE@JyfsQVX>xp<}X-vuk z#XN-%e4u(!EjhA*hLf-XdR2S(xSuj}lH%qMMdo}V^>g=y7@ETIXGCt&o^nqOb&WqS zWZLA?r+W5v50z~F92}F3^Q$uC1&l5NN-{AD8{mkV-#cMC<*u&u;$Rfv_#lAYyf;}-Dm2X z{SRDu<0LQj#-CcP8a&Xk8|TCcN|86EowRY>)&%-58!~TNG68QNs<{Kb>5^;-tdP73 zj3xo_D5n5v05&5p1Fit30U1CRP@k&WtAnR&cQ zZeTeBJ33!p2i#zcCFCrIB@u7I21u#izR%r2weYfcma+ABh=bQjfUrY0nR-q=` z;84>}*E^5}#NDWAZ({*4#h7|>_*#KZH4M0-=k#0bwP+2XZMAeo$?ha;Jk zxc8kP-d(y#g(dOpz&%%fdp4iWO}efqlk|YljY>BgT`f4&m)v7SJxNVKHKMeU)b;sX zt~io4`AkN~(ks+Y7)mop~A_YxPSW uu#RcW6TH)Ocgvzy|C?4%c8}Jw#9oJIu)P4Rxd1Ehs)vQSx4S)Fr1^itwt1NV diff --git a/py-client/sdk/__pycache__/trade.cpython-311.pyc b/py-client/sdk/__pycache__/trade.cpython-311.pyc index 3907e5a01d65342abc53bb9f87b22c1778e4a5a9..3871555c828b786eed3022403809498ac312eaa0 100644 GIT binary patch delta 4031 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 O`SFohfAX5QBKUs;nL*V6 diff --git a/py-client/strategy/ipo/__pycache__/boot.cpython-311.pyc b/py-client/strategy/ipo/__pycache__/boot.cpython-311.pyc index e500050d2abac42a6cbfdf44c7baac4158c15f19..141828ad7be657a7fc6939e0e575d29721f5800f 100644 GIT binary patch delta 1103 zcmZ`&OK1~O6g}@vW|C<#`P4M6*4ngVTcR#Rs|yhq+Aa!Gf2&qXg-jMHX;LOrDmt-M z{6YlnRPj?q{6r)Qm5LN}so+L!Bwz@1XZ>t+#1BOg#kO~JqQIRR}z89f*R2V)p(JM#Hu?U+z1f@h-#@tZ>2dna)alvd7iW*%`Y?9* z?fDaL9zE;~RT-D~Eg~DL$i)*w#%sQRYf)_9AC3%Y(L}t+hhvFkBqS7ta4Z^$Yehkg zBnM-fTFY8!Y@jGc2NJylYBU^CYXBtKZ5aoIj*3%jyfYp;96j8rPZvn!DQiE0KWPQYR=o3 z_cl(K_S`o+{B66ve}cLdz;8BQ?z;d0 delta 827 zcmaJ;U279j5IuKqb~hh;6PvdAXqu!JQ(fp&TMAMMs6~)M1p8L0i)2?wNt3YMAn3*- zD74TA%T*9W=u<`d66nA1L0SnI7Wx+?QVXTN$W2X46`TvhaL>${Gc$X!=0Nx(V?h8& zecoKUuWW`B4rD%xhATA4xI7c$3B#)n4Y3zZW^Z0Kn2YE~vV8 z0q+VIwoQQ@dYS<=h)cFY`~~gjoJK>EE6rl@S%W%B(RKBlmGvrI`W~kIL3$bjwh6Fv zHb%qeq$`~BcU;M($+HAgIgcCiUzmD|bwxK6muy9Z#1KrsOI^hbxH7N#26LCs z*#2opu;H58Jaoo0@-JG@`}mxa=UgdI>#E%kz*CCll2viUQC8|@#}?u}sa*2{rCQaf z*`=ao4*^&aTNvRt)w{t-05S1(g}+h9ee3y+JpZCDOfxy#0h6<9@&W66JJyPhwW5>F zdh?!m`_bF`Y_`Q_*QA3`^!3F0%*IRyp+J^D^ru(bTJ)PX{8bxnCx+UwR6CyQ2HAFI zyu-lKKcKSkPvJVk9bE!Ty_?wAGA%8$r)7>isb2F#u??LRbYFKqdjNnvD4dY2Cp^_K z%xcjvyr5w`t~+(xG7Me_Xe7rU1avaWUj?4$#E73@Pl>t-04M$%%T=>pw(|BZ0OHy! Sx!r3)m5ilHwuAqD<+OYjj3>6Wv{bN>MXC}XmJiC_P(tMH{Cg{DA)UK$K%Cur* znem9&b&<(zOw&?T%rGUZ(`aY|?LFJCb~2Bj>Eq! z?Yeu$r|ao!|9C%{D?Lf3vrL-ghK)y4VUlt&$~mLbB$d&bq2onjG?hh?rc5%Ern}|h wtA8L=G2`@5Zvt@5RC53y9YRQhy?U7%Y}d=wV5|PG2BUhJ8tl}|q&EP313E{WNdN!< diff --git a/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc b/py-client/strategy/trend/__pycache__/boot.cpython-311.pyc index 61924304e354915282aa4cd1a330bd0d46d93efc..7d38c505362adeb3057839e89a6bc37e695f9814 100644 GIT binary patch delta 1094 zcmah{T}WI<6h7nbUhl5^}rXb zOAIY!EB0wxSjs*uAu-Yzt1%Q3+J}a=fws`S%LTX6heE5_r*vNeK7>%lM1pOh!{M8m z^L^)hGsAp4TpDp-b-5e>01xiaRpNiB7P~WTG%PFpf^Zsi=f?sa6J_M5 z_q|OmbF~1vi=a4+_vmioP6qb-5!WojG2$!)nY#$Y{V#V{A;dTvusYU`L$KJJ8K7ZV zwRwoA5Mgv3WQ9qT;6LJtlfEg(P?Tj=$PDaT0c3`rt_v-Uw*c|b-(^3&FMCiueI$1x zJAGCO^*OPRSaBn&2b?O68l?drKE~u3xHL{9=1y`On*zcXE`TQE#AC z+U$QT*oJEX09zR-3|<0&ty-*2Vl6#Im;F;+IL`7%8L)fe9;VfQtywTBbcJv$G{`t{zeV__8w&p#^TInC5*fS3}ko~z=4XMMFI*L|bS!kR;UKXNP zUR!QlkNISUTpckVZbvKg&(59V^+&u3p!@C{Mg+;(hWa# j2T#bBpCxocroTlVq7OHIjrO9>VT6WJ75;a^?C1Oq?-4H` delta 789 zcmait?MoC<6voeKU%dM^v&+u9v%Bt$+p259A`+2k5{ac|L4uzGGua)@#nPrhqV9%7 zkcpIZz6eQd5E=-P?O#v?z4&ED781jcLG&T~1NsoNw1^aRx!iN^`905hwg%t!3u}RZ z7XaY<@RP!a=!WoGa{q7vJP^z8r8|e{Yb;1Za=XOqZhHZWjI&-CxmfgYC`eR@D)rp6 ziU8|q@30R7heDLhs2cefiPjfu*ks&h{?^zHhpy)L+e*ysD zp?EN}=;PQ6Bb`M*_ZJd19rw+m-p0M92HFUOqrm+KT?pJ)O4`f?wvT>F^=^d4E~A^w zSi%+Hfs$%tAIyv6n0Mc2+)F~d4IAxg0*vlj6oApQ-fGK^=)^WOO<4jz${Z;2H&!SFo9G zBqO4b8@ry5mC0R~cZ z>8=%Ssf1hR&hJXmWygwVMYN>Wiq!h@q$Qo0yRaQh?t#OVu0He5ZRT6_d|~nylb0on zDHW!eOd&nh7T>Ou_5fY6s^qb-AXrSUFxg}>Jx@jayCKPpv{<1`C6p;|rp_StQ7GLJ o`lOyZr^07d8AQh>;2_eq^e?dggT2 z007*3_fVJJFI@)lc_e@*z=UB~5-yQNk%7)ny2BC^b%C#wK#-Dr3j;9zlqI!Q}nyfG0?3S9Q%3g z%*GV6hexIE${wK5Sn4yZy5a;f?JZ!&tMFE!Ap&M!)uRV3U9*+0l86ERR;p90n+sKM zVx0sA|G_s`@Hph2p_fH~)yiuiuq5O~J|TZ@32)1WIc=u4>(kT5R4zkPMt1H-N}I}3 zEk&sZ0C<;jf!|fqyr`@+^bQXsZ)WLiav?XJF_Twju5~WVn@RrE)^)lc0Pxz3!veq^ z*zp95&@YdZ-I9DD?WnGN|3@|UL5;1nzKFe7<6COH2*lz4R9jzEpfR}i-S(A44T7jL z*6;$rhSE3^5jG;Nqc-`qLPl*e4X*ukbco&o0Kf_8%yo)SoF@1YXODt=qzRsOj=7Ja z+GL6IYpmZ7o{lDxyWJh%kh<744!$oF{iC?Jhpf`OZDx`MLK&@1O3(GvBWTfD`vu zgPFueq9}Sl*uYb0YZ5Es%GZ*u5%7)Z1j1Nli;g)BjkAK?8la+j8L%le$mX(=qLagEZ?LjW?J(y?QG zR>blSt;)}$jaJ-gspt=V5K3Gv6b(x<$T6s+P^A+5tO#8o(!64At#>$^oE8 z>9s%Pw(Od}{0qquHu*?AwCXH?7vl6_9O)l8;a9GDN%-Du=B z`$iX&F(FUf5W_}NAqg?0)Wo-&isqxr+S=^@J=APD)m2vUp3WeDWvt{?rSjLSbDQ}h z`s&^3I^4c}`rg~;<9E(Id{S0s0RU+E`&)w+2f!V?$u@)Dp?+8dfOmigFYpvk2dNP4 zr77$)LB`AQ6we0PkilypV}_tHWb_(CCa;Oy8-pbwv)4@erl2KM>MbSxlAtwI<}C}A zd&@&MuZ@CZz?(m!ymsDljPg1JyWki#0eGFqfG_=s^15gc47`=MUMago16-!F+oYiz z`0{b!ZN=l40N`?#3A}E?XCDXNQOxJ9;F(_VI7d1G;NF*Sq+Y+dboIj0+aISsnM$9X zUb=Sk`)?;wpMRD5daABFQkVMd!*uNW(&f*W-W{*&?+-=>0{)#5kr%|qfk=P9ilOzwVmGC}UkOLt>Gb81NpzQNd8haq(AM#Kd z(-uDIVKn!l=R3Qe=X&>bc5&^8xkG#R_ICAY#*Sb>2+NxJ5H7n<7DBB?0MO{BUu$&J zlN#Opm_|4MN~4>1X>@b5MmO(nWdT4eLsE{!hQtm4eI8mf9u*^_LRd3M!H6vRb20+} zM!%tcc#hbB0A7j*FZ}}Wl$YUYf#sPN0N`1H6P|^$ErD= z3;O&5`Hts>mq!Fi9{Du@^!JmY_DE!?aTq!J`|Hx@ChvYdrz<6WHo80$U3zysb!L9~ zkMpT>r_*m=yAwSvmY^JreqBCHAS`QiWLRS)S=3m6gcmg9@knqaBxof>Wn6&Q$|PCz z$-=-%F6;{lJsyKr!jUe=X%>zPMfi~*_N^TE@`x{pOdO|~IF66_IZm^2T!EfB?o;>y zW%lzEolhM(5fO)uygcFy%ST=c4D5J0Bp(?*xkKOGk?gWZWKjt7M|2Y!J}FkBYLK`A zK>95JL<@e4Y`e;~FS54i{^cV9adUQ!2P?a;NZCZyYx#A&dEDS-1p~jHw~n)`+{?(<@b+=mYvMQXu5s2|!q@VZ z3tk=R<_kw5Rip`>8M;ZWN>Fb+I^KYa+JDWN)zx3{S`ipN;ug|YI-nVb1 zu1=#reE|T=h*O$981WBr=rEBHnUe&+W;hy*_+-uL_l5mJu;`Id6yy;xtg$_ju;5>@ zWYW-E7y#;rFUg0>ls=4&r{n@og}OumT+Tf&Mh*qI916*%{2U5>g)V+i0S+CIv;f|% zU@Pc%xF6DF^vji2EMNsVv~ALO=mihcGmyRaP?|{+{E;v(dCVFU^1UK%M+I*~f^&;I zP*{Aau2!f!pNV_+Bs_cKb!~~dwiufzskyyro7%Kj-P9f5)ScMWjbpXRN4Lk= z33GDGBlzcbMfLd?r(TS)6PB1IW+4WuF+pKKTnhmHoB{yy%G;}lB}xIF=9x2ebygm5 z5qP#xse`%qc|);cF2Z|kFL;b2ZD@>B@26vvOYdL3_t}T3H{VX3yZ-&R6L)WXUH99A zeRZk1*V2ETzkB2A(!1k#Z+?(EcYS&4v*i!Rm)`#K(x+c9zw^bN=;={rRNm3EjH~@j z?N~;YduXB?QII9gEJucfFn3IN#Y2e*a}si{h}jwzPHY`L>J%P(xjJjF_(K%p-JPbt(zc#j!l6h?u; z+)Bs6PxItg?2Q!kLOuKnB=!XT3Ue4vP!t>n3Mk-d^p_C~JE_=Q`oh(FpPx#_ZltF_ zPfcD*U7b$N%-{Xy&D6|%YHoaK@>N~OsmY1-g|AYR=XEr~;PNy8^mvS7GfL9U`GbN_ z7lM>3NF6V0OOC!?B z(ek|R@qQ=j{6C4#7t0(I-V8A2211fn`z`C{1?%RIkIe-?2+xIYZE0QD(i-2gC$VKu z+}f6~wyD;(WJR^=+@v};O?T>lV;xCX<#fZ0M|IU_Oxelu)85Age$1_sf3T|e(@#IG z8d-HKIRPNnR?=3({H=y<+i3b*1J$_>+LutQWFlvG?)YL zi@?*0X)qTEi1C&vCdHtTG^l7M%)M6HaS%5vra^P|{#140-T!CTVM<{YV{VoFOzlN$ zVnVUfj)T~wFoo-kS^(X?G|MqWzFOR$Rz&0-Syi&n_B+LFzd+j7B+=lJulDTZ#4*DGXD@5z%-v7IS2rEzxfXx)MMAv7p~pA zdGX!{6L)W1P5o&ib^R}?&nD8bN!{%+_5bS2^q=OIr=s`1Jd=Ls%T-y*o#<)JKwx_X z9-Nv(7Ja|x?|Z(jV}DmC*W1_D_d;)1FF^(! zsmt15=slc!pjrH);FATO^U0d4qphc->p)xkfvy~b9^&Z$uUS`8p_fi_0iIx$_&BbN zC?s|u6q$7>LO0ZmWbcw@@{foj9xBShkrO11(y=S|s>TLnAtYkZmC(QtwMf&m1d}Kn z6$R>^Jn7~mn*?Zocv4W#w%BI@4CEZn1`~O+LTXo}=bg!G{XCiU;j%#e< zvF-(Tx9aXjmTsK$U#N@`9BXdb>lf_xvz>F@ar^d!eYW&dOm zeKr)gHYKc0sbd8!v=R~|qVdbR+(^NnAXsSi^;Qw%h-IY=yQ#bIMM2a$!Xm}iW6 z=pI%<8*dmQp-N&EhBqDuQU4lD9ah?4?pun!u|U$r->@1c$5^>0I~Rb$6zPR6)Btai zYxA6gIhZc~wpF^!g~Tf*mr4LG=T0tT1_cIl@J>Pjdl7hZ;rb+O8Zkr+V*WsyV#MT4 zF%0H3I$IFT@@>_wV6Y_3EEfXFg8PTuIGb(^JRgsZ)2Nr}t`RJ+BvqqZ)|&5q3?|h~FkP8nqi+L>01c;WI>WS**7pC@FJd=^vQ7+aRU;x3(XRc0%1wUGquL@0l!R+VHz_a z$eKZt#lWy;2u4l_qKKhDL=P#5ahMVmg9*9#}i4bYvNfX2axn6t*(T1 zBcbc>ml~axAHnFf#Ekz_4)(RvTRv`x+qNcbTQfkJtCOy($>!VcHPgoTE$>=ppN?1U zOjPYutD3Lvio16w+`DhNTNd0cad&IN-FnO2x!~@MyZ0vCdt>HgspH&JuRk?;EM8ih zD6O4+a-np)TDtw3S^Z6)`WRkh@|3MUVcU9@neV>x?5DOXwj0j4ttDY=iLtkx>yoyr zq@!wTebP~pbgfOe>XWWDx7XB8Dd+z%^@pTu?Nn=W-KNC4Z5fBzWw{S#m*qz!F;m73 zFg5>Ir*;Ty;N2lf=Gej47HacWfwZ z3d8^6j5)DkJ4XWq|w{P*8pym#%7OH=bWa`Vjc2j8Tw|0O+f zDm`TzPgM4Ti1joNManoHgGM(#MjT1^K@>7^J_+BdtE-DfN#6Fer6m}UWPcxrF$xM2aw)NAaahqqpFR`P2!Pc(Y z+A{_yvoDgaYHKIei5?F_AVM=>mMLk>aAY`pWX8Q~rj>KH4h|@;{{EE;6-jDGH~in5 zKY<&488?bMWs7#2-}7Sq*10D?dFI1s;`L35`lgJ5MIU3)$5`TH7I3dal-Nv2tRrc) zPwYE)@b!b!_0w|P+K{j|sN~8pS*DfmqeTzu04q2iqh4zxMLMkJ=)Fel;c4H)lIjq_ zTzwRaU>>6m)!5h138Y8f!s?ZW%^$3b=0b$jtICDE#3INJ^6Qq080*D4BpZ=zLh=O4 z--<_;fIlS2$0EG=432jrc@fDmBzUwSHmH}Iuy!auk|j8$^l?!wJIOYxY-5Hs7}jUt z0i+y^&J0Z(c4r_^OArxdUB&g=fM8$Z`k?`PTrEDf)U|&Oev5=>Mi@717SI zR3|+{0c048qLT2e3ePUWCbjrlgz_l)C1Imld?n!#^+8t>)~dx<5-Qc=YZ0DMAAaGn zs9Ci)srII5S+a8N7XEY*h6NTp1(KrP1oihG|}<>f=;>f~wEZ mCDfV>{F2vwK)S1ruWJCj}LiD1pL21)+E^g literal 11407 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 diff --git a/py-client/strategy/trend/boot.py b/py-client/strategy/trend/boot.py index 9789485..79f0cb2 100644 --- a/py-client/strategy/trend/boot.py +++ b/py-client/strategy/trend/boot.py @@ -73,15 +73,15 @@ def StartTrend() -> None: ) assets = client.assets() _, positions = client.positions() + order_book = OrderBook() + order_book.refresh() storeState = State.for_strategy( config.global_config.qmt_data_dir, config.account_config.strategy, config.account_config.account_id, ) - orders = client.trade_detail_data("order") - deals = client.deals() - storeState.reconcile(positions, orders, deals) + storeState.reconcile(positions, order_book.data) # 获取本策略的信号开仓数据 signals = init_signals( @@ -93,7 +93,7 @@ def StartTrend() -> None: global_cfg=config.global_config, account_cfg=config.account_config, state=storeState, - orders=OrderBook(), + orders=order_book, open_watch=DipWatch(), add_watch=DipWatch(), profit_tracker=GridTrailingTracker(config.account_config.grid_step_pct), @@ -120,7 +120,7 @@ def RunOnce(run: Runtime, signals) -> None: # 1. 取消超过有效期仍未完成的委托订单。 try: - run.orders.cancel_expired(run.client) + run.orders.refresh(run.client) except Exception: logging.exception("取消过期订单失败") diff --git a/py-client/strategy/trend/order.py b/py-client/strategy/trend/order.py index 45afd74..c666cf5 100644 --- a/py-client/strategy/trend/order.py +++ b/py-client/strategy/trend/order.py @@ -12,6 +12,9 @@ from sdk import ORDER_SIDE_BY_OFFSET, Client, OrderItem # 表示委托仍在处理、可能继续成交的 QMT 状态。 BUSY_STATUSES = {"48", "49", "50", "51", "52", "55"} +COMPLETED_STATUSES = {"56"} +TRACKED_STATUSES = BUSY_STATUSES | COMPLETED_STATUSES +CANCELABLE_STATUSES = {"49", "50", "51", "52"} @dataclass(frozen=True, slots=True) @@ -32,7 +35,7 @@ class OrderBook: def __init__(self, lock_timeout_sec: float = 180, cancel_timeout_sec: float = 10) -> None: self.lock_timeout_sec = max(0.0, float(lock_timeout_sec)) self.cancel_timeout_sec = timedelta(seconds=cancel_timeout_sec) - self.data: dict[str, OrderItem] = {} + self.data: list[OrderItem] = [] self.lock: dict[str, float] = {} self.mutex = Lock() @@ -44,42 +47,45 @@ class OrderBook: def busy(self, code: str, side: str) -> bool: """判断证券是否存在仍在处理中的同方向委托。""" with self.mutex: - self._clear_expired_locks(datetime.now().timestamp()) key = f"{side}-{code}" return key in self.lock def refresh(self, client: Client) -> None: - """从 QMT 刷新当前委托明细和方向索引。""" + """从 QMT 刷新进行中和已完成委托,并撤销超时的活动委托。""" orders = client.trade_detail_data("order") - parsed_orders = [(f"{item.side}-{item.code}", item) for item in orders] - now_timestamp = datetime.now().timestamp() - with self.mutex: - self.data = {key: item for key, item in parsed_orders} - self.lock = { - key: ( + current = datetime.now() + now_timestamp = current.timestamp() + data: list[OrderItem] = [] + lock: dict[str, float] = {} + + for item in orders: + # 不处理状态不对的 + if item.status not in TRACKED_STATUSES: + continue + # 清理过期的 + if ( + item.created_at is not None + and item.status in CANCELABLE_STATUSES + and current - item.created_at > self.cancel_timeout_sec + ): + client.cancel_by_id(item.id) + continue + + # 缓存本次有效订单 + data.append(item) + + if item.status in BUSY_STATUSES: + key = f"{item.side}-{item.code}" + lock[key] = ( item.created_at.timestamp() if item.created_at is not None else now_timestamp ) - for key, item in parsed_orders - if item.status in BUSY_STATUSES - } - self._clear_expired_locks(now_timestamp) + - def cancel_expired(self, client: Any, now: datetime | None = None) -> None: - """尝试撤销超过有效期且具有委托编号的订单。""" - self.refresh(client) - current = now or datetime.now() - - # 使用快照遍历,避免网络调用期间长期持有互斥锁。 - for order in list(self.data.values()): - if ( - order.created_at is not None - and order.status in {"49", "50", "51", "52"} - and current - order.created_at > self.cancel_timeout_sec - and order.id - ): - client.cancel_by_id(order.id) + with self.mutex: + self.data = data + self.lock = lock def place(self, request: PlaceOrderRequest) -> bool: """按最新价提交委托,并立即写入本地方向锁。""" @@ -112,13 +118,3 @@ class OrderBook: self.data[key] = pending self.lock[key] = pending.created_at.timestamp() return True - - def _clear_expired_locks(self, now_timestamp: float) -> None: - """清理过期方向锁;调用方必须已持有 ``mutex``。""" - expired = [ - key - for key, created_at in self.lock.items() - if now_timestamp - created_at >= self.lock_timeout_sec - ] - for key in expired: - self.lock.pop(key, None) diff --git a/py-client/strategy/trend/state.py b/py-client/strategy/trend/state.py index 4fb0bd9..8c092fb 100644 --- a/py-client/strategy/trend/state.py +++ b/py-client/strategy/trend/state.py @@ -136,7 +136,6 @@ class State: self, positions: Iterable[PositionItem], orders: list[OrderItem], - deals: list[dict[str, str]], ) -> None: """用真实持仓、委托和成交恢复本地状态,不增加持久化字段。""" position_list = list(positions) diff --git a/py-client/tests/__pycache__/test_ipo.cpython-311.pyc b/py-client/tests/__pycache__/test_ipo.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f49a41fa0f158925939aa5e04e2e6f028515b0f GIT binary patch literal 10574 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