From 8eb44440d39caafc352dd390688017892d4f5bfe Mon Sep 17 00:00:00 2001 From: yanweidong Date: Mon, 7 Sep 2026 18:18:00 +0800 Subject: [PATCH] update etc/* --- py-client/etc/_global.yaml | 13 ++++- py-client/etc/cai_cai.yaml | 13 +++++ py-client/etc/fu_xing.yaml | 13 +++++ py-client/etc/hu.yaml | 13 +++++ py-client/etc/liao.yaml | 13 +++++ py-client/etc/long.yaml | 13 +++++ py-client/etc/test.yaml | 13 +++++ py-client/etc/tong_zhao.yaml | 13 +++++ py-client/etc/wen_ting.yaml | 13 +++++ py-client/etc/xiao_dong.yaml | 13 +++++ py-client/etc/yanweidong.yaml | 13 +++++ py-client/etc/yin_fei.yaml | 13 +++++ py-client/etc/zhang.yaml | 13 +++++ .../libs/__pycache__/order.cpython-311.pyc | Bin 8514 -> 8642 bytes .../__pycache__/orderbook.cpython-311.pyc | Bin 12964 -> 13765 bytes .../libs/__pycache__/overview.cpython-311.pyc | Bin 1722 -> 1577 bytes py-client/libs/orderbook.py | 51 +++++++++--------- .../sdk/__pycache__/models.cpython-311.pyc | Bin 21776 -> 12606 bytes .../sdk/__pycache__/portfolio.cpython-311.pyc | Bin 5895 -> 5492 bytes py-client/sdk/models.py | 4 +- .../__pycache__/positions.cpython-311.pyc | Bin 9000 -> 8915 bytes py-client/strategy/trend/positions.py | 33 ++++++------ .../zt/__pycache__/state.cpython-311.pyc | Bin 11095 -> 11027 bytes py-client/tests/test_orderbook.py | 12 ++--- 24 files changed, 217 insertions(+), 52 deletions(-) create mode 100644 py-client/etc/cai_cai.yaml create mode 100644 py-client/etc/fu_xing.yaml create mode 100644 py-client/etc/hu.yaml create mode 100644 py-client/etc/liao.yaml create mode 100644 py-client/etc/long.yaml create mode 100644 py-client/etc/test.yaml create mode 100644 py-client/etc/tong_zhao.yaml create mode 100644 py-client/etc/wen_ting.yaml create mode 100644 py-client/etc/xiao_dong.yaml create mode 100644 py-client/etc/yanweidong.yaml create mode 100644 py-client/etc/yin_fei.yaml create mode 100644 py-client/etc/zhang.yaml diff --git a/py-client/etc/_global.yaml b/py-client/etc/_global.yaml index 14dcd85..4ccfb88 100644 --- a/py-client/etc/_global.yaml +++ b/py-client/etc/_global.yaml @@ -3,7 +3,18 @@ qmt_token: QMTbyYanweidong api_host: http://139.224.247.176:13499 qmt_data_dir: D:/qmt_strategy_data hosts: - DESKTOP-39H91QV: dev.yaml + desktop-t5lh34v: dev.yaml + t8zznqs49f1ju7q: liao.yaml + 3zaewgoemkkhvst: zhang.yaml + ba0wpr7xkrbr5l7: hu.yaml + f7tib45aqk4n10h: test.yaml + dpxrcond71s657r: long.yaml + hwoy9gjt1612wq6: wen_ting.yaml + n31pqopr0xlunui: tong_zhao.yaml + 3xrfluszqg98sgm: cai_cai.yaml + rfo1dc7c5nn2f1c: fu_xing.yaml + rfo1dc7ucpwgmvk: xiao_dong.yaml + 243wwi09wfwllhg: yin_fei.yaml signals: dcm: {url: /a/dcm_signal, timezone: "*", gt_last_price_is_open: false} morning: {url: /a/morning_signal, timezone: "9:30-10:30", gt_last_price_is_open: true} diff --git a/py-client/etc/cai_cai.yaml b/py-client/etc/cai_cai.yaml new file mode 100644 index 0000000..0a4e119 --- /dev/null +++ b/py-client/etc/cai_cai.yaml @@ -0,0 +1,13 @@ +account_id: 8886966846 +host_key: cai_cai +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/fu_xing.yaml b/py-client/etc/fu_xing.yaml new file mode 100644 index 0000000..154d9d7 --- /dev/null +++ b/py-client/etc/fu_xing.yaml @@ -0,0 +1,13 @@ +account_id: 8886120710 +host_key: fu_xing +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/hu.yaml b/py-client/etc/hu.yaml new file mode 100644 index 0000000..32c83e0 --- /dev/null +++ b/py-client/etc/hu.yaml @@ -0,0 +1,13 @@ +account_id: 8889975553 +host_key: hu +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/liao.yaml b/py-client/etc/liao.yaml new file mode 100644 index 0000000..852a3e8 --- /dev/null +++ b/py-client/etc/liao.yaml @@ -0,0 +1,13 @@ +account_id: 8889399698 +host_key: liao +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/long.yaml b/py-client/etc/long.yaml new file mode 100644 index 0000000..2d3f539 --- /dev/null +++ b/py-client/etc/long.yaml @@ -0,0 +1,13 @@ +account_id: 8886508526 +host_key: long +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/test.yaml b/py-client/etc/test.yaml new file mode 100644 index 0000000..2f76efd --- /dev/null +++ b/py-client/etc/test.yaml @@ -0,0 +1,13 @@ +account_id: 88017860 +host_key: test +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/tong_zhao.yaml b/py-client/etc/tong_zhao.yaml new file mode 100644 index 0000000..346ecc3 --- /dev/null +++ b/py-client/etc/tong_zhao.yaml @@ -0,0 +1,13 @@ +account_id: 8886225815 +host_key: tong_zhao +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/wen_ting.yaml b/py-client/etc/wen_ting.yaml new file mode 100644 index 0000000..756ec8e --- /dev/null +++ b/py-client/etc/wen_ting.yaml @@ -0,0 +1,13 @@ +account_id: 8886441125 +host_key: wen_ting +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/xiao_dong.yaml b/py-client/etc/xiao_dong.yaml new file mode 100644 index 0000000..8a0854e --- /dev/null +++ b/py-client/etc/xiao_dong.yaml @@ -0,0 +1,13 @@ +account_id: 8887377770 +host_key: xiao_dong +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/yanweidong.yaml b/py-client/etc/yanweidong.yaml new file mode 100644 index 0000000..b289d10 --- /dev/null +++ b/py-client/etc/yanweidong.yaml @@ -0,0 +1,13 @@ +account_id: 8889292292 +host_key: yanweidong +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/yin_fei.yaml b/py-client/etc/yin_fei.yaml new file mode 100644 index 0000000..9533e5c --- /dev/null +++ b/py-client/etc/yin_fei.yaml @@ -0,0 +1,13 @@ +account_id: 8891110937 +host_key: yin_fei +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/etc/zhang.yaml b/py-client/etc/zhang.yaml new file mode 100644 index 0000000..0526a0d --- /dev/null +++ b/py-client/etc/zhang.yaml @@ -0,0 +1,13 @@ +account_id: 8889616198 +host_key: zhang +buy_value: 5000 +min_cash_ratio: 0.10 +loss_trigger_pct: -10 +grid_step_pct: 1 +min_profit_pct: 2 +strategy: trend +signal_allow: ["morning","tail","arbitrage"] +enable_loss_add_position: True +enable_auto_ipo: True +excluded_codes: + - "00000.SZ" diff --git a/py-client/libs/__pycache__/order.cpython-311.pyc b/py-client/libs/__pycache__/order.cpython-311.pyc index d7b390536dcf32a1e8ac9bc1357a5750f1789551..6af540369dfb479e0300277aaf3a8d2e3ded0638 100644 GIT binary patch delta 814 zcmZus-%Aux6h7CPb#ixp?da8gA21!Kvl+up}*&ccbtfi#KT^L~zgnF=lpno7{b*#X{;d0OSednC-l+KmT^D7+Z z1prtZd}X9VYy5p5S|tm<(ZJvwV=)f18<;U@@*|)ev1;<&m_{ag)O3(cve-Qh08E3~ zi9O^j8=_$O5J|BiuEAw7V|YnUR>&+H(0nd>?+a#({Rzt)NwGl+44$mBx_{}Qg-5NZ z+gw}t08^MT_6N>*0WcUM5x5}oI~I`SoWmo)^;vp`1DLC~TFGH0c+2B>a))8Y_}8oC z;;(6dx3pU!$iZ(ow z0!(AbXfA?17&2ip%qLOJDaBYx@>veoS;^u$--q;w=>dQ(Dwn@wb_0Ovv~IC^GdpQ! zNKouzx4Z=_KXE%Vk@tr5l;*?F0NcT)y+2?>z2WYAq?f6-5UC zz`Y+!`h@$l^so!B(9^1)e(X9m7M$e?uUpKziBji30szx!;JoWVb!X0BOoI_8T*XGO z3q4+buWJv4*E{K)pweZb|G{qO+*iWuUCdPx7~2m5y2$cZpjpZtZxG-EGR;^xa8)nU z!My4bu@GM0-8bU^AQ07MW}32^%(!g_f)$0S`$2f!N&7|jC<3u*))^6C)>aDbS@dqk zHIDGQon_{a_i-oP7W;;dF$G`%j6Q?|lMb<}X4_dCmIl#HFG$BjAp&|2t0n+}SPA4j zOd%YBoR=<3Bi{dC#+MTGr{u>(Rg}}{@*5lgv@M0=UE`$5Y_y;ZbA}H9=qF_YJE+t7 z9-Va68B1=--ShW1j>hV;87;-rGKKQ3x*V>{;g;fkE-r{KwAY1~g?ATME`PJG+8cpn zGmva3siu;uD=C_EMWij&vpBvH9ImTo(8sP&c!h7M(WV-$tI?L)Tft}NpPt=R{fp;X zo@~q0yJX*ec-nT2V3xYNw}ZAZE-iGd3j^smw;scEoU5sFCSs{YteH4p8^%n$>Q>jR zLfdhtRGgg3O%}C$b<@*_c$NP4hVdF5^bO$+ddYVN^VPENy9M*~W?&q(>X*Q%>H2ke L6tmS6N1osxQ5~W_ diff --git a/py-client/libs/__pycache__/orderbook.cpython-311.pyc b/py-client/libs/__pycache__/orderbook.cpython-311.pyc index 8ee035d20a409ae04931add80023a74ce3459d82..ee891c48e6af3ee391ff4367b54c6d8e73f03990 100644 GIT binary patch literal 13765 zcmc&bYit|GnX}yGQxs{Flts(0jV#-uttgHkv8|V@2W`n#C`Xiiu_A||xht6#AIk2^ z58bNg(cRR#!U^Lg>&7|9rM(9YTMAk7BZFFT_{JObA^@ z3>roZ!I%<6(ll%$;GIm6!zBJo4O0xkPziI=GHk(h=7cqA8@46w!*={_NjQ>@VF!M< zCaRLoVJCjKC90FIVOP>U>?ROnA6{ib>}tj_gG`9Ev+kb|2z@{lr__Uff)M(k_=$|Q z!yeqWs?gSDtbKS}#yN!$8upqHYcnC%{m^lIOf}=m)|959ORUE@>U)TBuLR4innA4R z;q!VAF{`hdSM0&_=pHa$YZ&iJeX!ndF=O8hV!e-?am`ipaIFa)M$DQS#MJ)8gwO}3 z;vxoT0-#N9kmm zVH12Solddzc`h!n96iBuG!qq~r=vXE`~~zMAk?a8DwP(ZxWiC@P_3~>LWxL!DjyLAvh{9U2&-gU|Pchr&8E8XYuE({YCG3k?Mi2M6h6gMH6-4xXfs22awR z$A<>`LfwPGXM>@kCJf07>DYKAmS$LbDERyk?lg3~zh7UQiY6;+>7L-B&g1<<^tNpp zAQR`<7~owTS1Uf3PE01*Vp*y4QuCd3cW}aQV2DGN>2{sj(;Nmfs9t?K& zFVj{B7fbWP!@))q>8KEy;L@YGZ!Ky z7LVv?eITUgnQ}#-)luwrIX=Sz;;+nOX^vsJ2!D}}#F+|o3(R4FXzQT2Z7cE!ZkkBP zqKQW|F2U%VbL{9tShK)hcnE+rh=(NvzC-}5%&?=QJS#*-6Vb7yqZctYz|f7mb~n+x z_B7FZ_BYXc4g?D5FGrGv4zwzrI9ZAFD&$W|{AjcpO{OPPmGYv{!~jv*a4GF-%UK}# zc%?wqYB?5!&m&eEbPD?jN%r{Mfhjs-ps;~ZkysuI444gtA@-CLu-g|9w>nM;H;x!Qr>pS+n(J!7kul8 z_O8!4pJpVvG^#36!&GfwC>$Id0$DJi7s^wnCVI*dpigx69}kAq>|(8#pMy|0))1fSJ~eo`8%@wymy{|XRY?7 z&oN3G@i{mvCsqXEZnwM(2Iru~Sy_f~FDi{x)9 zZxDRxA3VYd5ODVh0^gEF!vuqdO$;$iGJeJ~1ODV%#x_F@o0&SsK0^&# zSSz!Rsh**Xp4qUCS4Lg{P%qFIG#ynib_`)batM&oVpIzzn_*6&H zqNn*(bb>#V7Br_LIx)efm?zVz#6@ipo9R%R=3{5rWRy(s7LFArxs*zU(kV7pa&izt77b0}t4jo+DCmTnNElr%5k*S1ari3rgTF8#LK5uw z4^GBq5K+WjtP|1MQg3Hr7C2=K?z}NE1VemiGCF7k5>}U?M3mKyT299CjriO$oeeV=u&cA(9>sRC6|<`OP4d>?J!@HDg{QWCXLHWl6`TK#ZR2g*#;mZ&NVbi#tyQtLO19R!)xNo*%cuV7)DI$W zMda!&O7)gJBJ5ihJUOT9j&uEO=lZKBWM_loY>=D{d6KYe^%&?&fczRV{JCQG%{SjH zS9j0me8c{_{k5vusto?|pwoW0e_hum^42D*YqRy%R-$XO^?`?fIT07w-Ob(F>c-P4 zgK&ejCqaz7h{cGW$I3h)qO&D_T1xHHgrK9Kvn5^=i3s$LlSp6+`eLJ|J*{BGq$h=d zS+y1>s9FpAuWc&Jh3qACx7s%w znIF1xa?vDJ@0P1~E7iL*rn_tDE9)|*Sy#@zI%CH|*040d?s#c_xK#Y0Y)L@qlaXgER-xE)!Y?4+!r$J9Kd*isKGwCj8(uXzh;xHEp@IZ^-6W} zrfGI9*uxyqE7-&k^(q-&T>8A;@Ot2AgX&m1IngmyUzR%{ubSJig~)d_mtmqnm|L(M zlKf-Zb93{&cYZ`!yZvW9i{2Z3ANG}MG$W-p9PAHv57FD{LxTg)mJQ7R3$z1->eTy8 zTsQDtu#)c%1K&Lcx~FyM`jXmnlbj3BZ&Yd;f7Ym(g#0#>XvFz>6@g1+Fk!#sCD)&$v;AZw_y)F{{UAeSJ*sCfdr0TY*T<3JqpFA!K+ zEGOqldx}`_EDYxHo0jLCt~ZXneq`>v?A)X{H%ZP-IlR9gd;X*DR-M$(%AKQ1=cwc# zll^0ge=O6N!wYhg`)KOdQ__)f`Cvjhn2>x)*_Tv&$xJYBg>m#_e2K^VS~se`cIi9T zAC;Xf1=C9Ynw{HF-Da#-YwECC-9Tq+-Wk3!j1{Y7gNFxM{$sLhJ$b#;*JU>U?trsv zJ$cJab=mE=>`;EoNx*wGeqT>@(bij=i7wizQa}trEg#?rhb|MbZ?R;4B|_F93h#aR0)A)>P-d>LXK1@e_6)V=2vxue@cEGx1P9~9HYgqbFVC(0m|nu)QGW1Y@DBa&I2@n25H-ne=ZG_2!$rZNieA*M6-EJ9h=WN??F?V!1vaS#W$C^id@Q6{=I7XA5HZTJG{?R?8RuAr z1D9f|t{-BsKz=&S} zmp&k#`~swd>d?gmJzO6YS+vNp>No)hLP3s8a~y1=>KS8&LKI8W`Ef=iqp6FkMVlpe z0-($|63sma@^%oi7a#*Mp^~Zed6k0rqiT=y>CrToj0!55U{k6!&NK0`xDcSYqX2&h z&qPCzgJ6bH535zW&6uiLc8|uO)hk#n-*bBvHx16wb40f1+R??QZ#V3b8ur}vtd}+n z$ev@0=a}R?cHiZj8+t74bsv^*|12=7xJ?)C8 zU2?YPwr*Fp?z{QK?X9iS*48&r$Lh-~cITJ3vbXz_`~`o;PWpVz)KJ-PLChRpQKwzWC8C*#00 zjjgQ*u0)&{UML>=o-)L6O3L^{>_o*Ou0iymQ_q0#Dl2Ba5;;e3TMc!la|E|RM9Vu( zm4a9_>Dz*6oZTmycoRqvqauGCwQZC~d(ku{QrLx~vO1HYoCIAwMKmoRF)}Iwqh$QH z5u9)7cA;!ZZR?Y9Mq0cFOWS}Qiw|r{b7z2uLC|PscU8gcPJ*IruCN3=*P_Y%N> zQ5`UA);HMXsy)S?*G^Y7X@DJhSVSB(WKus|t|Es`6an}TxinDl&9ItWkhsoi&;I(Yl3gCA4!Q$gja;GBKF zL8;pzuWI@x=k@~|dvi`t=FqZ6KVfgvY<|Mt2B2+V@rPayU2R>k-)Y=`yK%qV*rGJH z$j(;9*(y0(A?Tw)VsHrhv_a5ESB5JpvO>_OvbX~3FYIk;24r ze9PnP+DqQrNOjfQZ`DKjtt|w+Z^iF>sjdUoTWv(w0V{T`9(b@ECIxo?vwsVoE{kCYob~Xgn29 zjnREQJUyD`XdJ+V0(=I+Hydo6QV3yxIfPJaJUSCfkuEUnjgsO`)2u(NodX0+IEsMP zZP75H;sTpA*d^GTZmJ;pQZRM7Fv9D=3iVnT!E;!97Ki5cymj#Up@ls^>c7@sD#o%J zuJTZP^c-7^q=CDvpM&bcd{!EC%D>WdGSD)Bhb~Z&Hq_0NlIO7OIjndN%eG#{)+-es zZ3e0tHegI*)DdR$7$C}S(Bdzu>`Ue= zme*E{O|({O&6QvU2#XhzNIiBdIOHw1A}d?Li4Q|mmacTh^6j8Slr6cp`edXYxb_)F z0sABzX?*t4)%!o2|9tk9&wlgf{f|EQ z-oX>p9q<_hB?xsKYlUNdU{w*Fs-7m|NPj4Boe+uZ#1BlfuA)#R)YZoZ!hJ)11EEOa z8eW*=DkRbaM;l0rC6QH-Vmgsnf_W3#!#pk_$rsX|MM0|B^fab0~p_9W#%!_{N+t5zur+Q+NC-&*_w_E1f>&Ip94#m4e^7j6+ z=NHd@yhYyAtL*8OcJ^ve`dqW=k5>lNN?QyD!rNFLi|ABMWkCHk(>dbjPB{24hcrfE z)7OL%2X_+iv3P*Q*B7ue$en|EgSe#WOIj@UZ!4n86$qEMdLCM~B80xVgz|{0b(OPw zzS^93&77!s8y13+_i4%dbl!|SHFG22fvsw|hl?cd(-_?;x)5tF-$ba0u}^L93HAqv zf)&N|-}D9tgZgIe^ud6WV*yhfg+2vu*cgt$Tgi0hj=(3VBGp}Dg5$^F{s@MZ#c#cjx@HPRV&9P)8|-*2fLnr37gV|s5bDQKB^5XISZ@iHsMvfhwbO8 zRZ`XZyKc|i-q)sPr>=HqscVjR2CfX;cJGkfJMONbr6;=OH9g9j9%)ri&cESmEZcBx z`#b3?X=!7#w6R(7KLufIV78l+ABn#f|Mk1S{jTH-$-a={3uWv%?~b{Xl6OaTt>oPS zMtT=E)w_sH_g%NAKzt`o-Z}Bo?GrD_Cr&FTPD`Gc?1?F!nCy-z?pPiX)m;Rh$#>*6 zoywX{X;o*Qgu?sFMdoex-I|eZv+vI1%w!-BOepu(ZFs-s-4vPB}QBN9obnaKpa zJ0p>oC!>i%jWrTs(y>T{1IdQnTFiT@lZX57u_P;;Ni&+`n*xYQ$bhl58$MtrXkrWO zaGdo6hy4btpi6~cj_Q@D-aKV9`|`+``AD-TkBphaYHrLUW9C5?Pu}D;d-JH6eMusV zXJ$kz-EN1zjoBKLxes`)GPn5v_F;)kaKdoKlsDgheh$W&t&+^#m;lP*Df`wMN{R5C7u2hm|#x+8KLjrCWl$nLei3F>Y zi--Dx{XOAAfI<7<;A)&oolVD6+;^cR7Mgeq@Wrdrwmh)4X&c|c{Uh9!g1xCSA(STx zg2I04JEWSPc=EH zOP2hL1oHalwrDpY7cGmHMX?ZCt_{kyL8Ue*dxDB5c*&h}c{8kbIdS38!lA|ea#Neq z)Fye`WpBIUZI@l`imP4vPFQw@FIDAyb#sU2+veNe>A2D%`?f2-?Gjp@r%dK2=b888 z@5UG0^2Ytj#{EDuPvR`+_P%lP^^4kN!G*Ns?~wf+ioZj4cPQ?TJXwU(T3C>^>ih9m zfg3K4OfT228kZh?t}10W)qJBbKOjz>3?Zh%IU# zuv3UL4>)w_MZ{T7AkO-p4x#sTg>4KtIl2dVY>Ax+p`LA>VTot&ocin3$iLmW`o(vj z|90w6XKr8nK?Q4I`!(99G-FHUs{^_&HU%vJ2$nkryoQG1Z!B{LV1*LF2Ci*>;Vhly%VmP+X zLn(%!$c00ahf+*jP~xROA30nu_{B5ANQa-TU(wpPbA^{((c|mvT;a(dv=Z|X zi~=7GhGXH_zQEylBoPH1L)2mM}q|w?Iyy_M;*LSVI32GSy2f;>4!1 z$r37?fG_ z5JK-4aSfPwBR8L$J+0r&E#Rt7Fas8DAy<8Z8L)D5dXQ(4V(tP<*&2@@9O~N23u0K5 zidvNwW5Gdje_RsTV2opfgM)mGTNRH*jSC^=M~Nh{J#7yNOwsp(l~Z9MK)6ccLQ{g?1te zQLr;x30J9TcLrE{kcam7dUT3$FevabNmNYy(Xc25;s-r;0SF^l5kiW&Xpa>=mM4W4 zc}cMo*#dhL=0wFnkSO}-K`tx^;72Q_KqwxI@gYgE6Gr02kPse}6hlwjCf}A8g^9$2 zoQGBzk&o;ptLeBsBD`9bWgkA--ni>XTsXMvP$C$UcI^r8TXiTZ?HW9`DijIxF=>ZL7=J>SSA8j;73H90T14 z$Olm2#~G_1e)yr%*e#RojQN!Lq;=Gq!hfO*A@q-R^II3w*B3Lb%Z%5TQ?1L44_)G+ zNLb?6G_;X-5st?~MM*#iM?5q_)b}rAourn?lEfs@fui(HmyKacDlr;5P?XFh70Aa^ zAl;bX?kyrAhY{3cJRy1XiZQ=I#hB+7!U%MC{D@)|;zt5|gCQv{9P{Xe1;CUG;Vr^$ zSXKaRLM=i_^SbkRUIf79v1A)H5KY)OeAc>cW+&KniiX6Ej28TKw&0 zs}Jiq=0|4he_}TM^Ayj|gHGy_sHDP^bP|xFUhhqCQ+cMyd`G=3RQwL6-KeD zGx!yKtMA1Qzvc}Ct}0;uM$G(RSa#RKTjJ2%!gP&DlpCoxbfa^7AckhZp}0aR41~*9 zbc(KFwL%N=BWg~4Xju=Vp?Gw#d1z@#KYG`?Q`^+xhOi2x@riQrdS<;uX&ap5h2O?qcn6u}NaPy4!u-Z0k-o%z4b% z5@8jg81qI*08J@WLFI<38f+CE;bV#wJB)!4__Q9Tq;5(xL{Mmuz#yt;KAg>=eUqJV zjxdF-OeF(Bn`6{v*X8aUZjm}`bDY_HYV+A6Y1`tAZLw@yoW(Ev+EZUNe%dH+45XW0 z$uzwp*9OzI!Axy1)se*{x+Z)v^y!ei`CxiOB(otRyQ67$G~uoStB+km=zvc zB4JVb7m&~08jlrTI5q;n$LGPnDk=tb;ix24?xSJFqw@z>>JaMi_xQSdA?WKOY>Jax zg`x@Dy=Aew7f0qeuqeghUUk&%#W6OC=ZZxYUVB*xnZ5bY*gGu{_G+VAuPRI}LpoEW zLvRWQy(G}gBP3yE;ekYg9?ik~TRQuEJ#2lWT9J6!Ms1+yWgAJn)~Lxvc-cl(>cPu4 zLZ+c?!}-#vp++MiMIBIpa9x$mtCB zAeD0~X~(IgE=h5Q_2BZL1I1W!aII8R zqQQY;1gNFPxV;2ZDrGQ^(nzUjVTNgGacQjFMdOSIv2!b|P157DN^qs3#U?CG(wvDi z|3X)CxqgQ@OOocyoV7x)l{0C3-_{S)Njgb!HcS_YH0+6u2%(m(9qi&tgOIzN>< zd;8Oi_g;PN-n(yqJ91or;|x99b4--@C{c}UM?21ykkI%rpVyykJ}Vd$cvj#KCBg#F zX*@4r*)`yAg0Q@VC~Q!6Hw;tiuq#PPs^~y#RN`*65UE2gE%Vw?KRQoQX!Hp%LRTpN z6-KdyMNpr?Scq5jdn56nq%cuP*O`8{I79lw!AOEvYnzAW_51i3e{@i2 z9;z>C8qf~`fe*z6wF6s#41?-vMhM+SchLxv9Rb-9_@?^w(AZ;_s?*LD8RrVw+5Q*i zWBWBey}CWKx?T3R6DV~}T)ib*A%mGuQQ@qk$VL;Q#O~o)vil*guaK@{^I69NK=D06 zf{Q>aHg$gT9w<5gJrMDS)T(vun(PV(AA$`2-;@2=HzdIv6{q z7zp`&RCdfyMeb_tA8PF_u#>ql@VFxwdo~c`VZOKGklU&zy z)3rce*q?T7&$zbBw(U0^?z6ooBcqWNebeg5znkv98{NAmx_70!U(R&DEIR^eMQZ#dpEk|U zI;%3y#j>;g(z=W5-)X+sd}G<#iDhfk%hqLc9ZEY+NyGjHsvv6iu?&h3}0o|UVf9e0lhFH_^8i*w2I<=(4H zt}ea0^n)GbIn|zBxFkiVwxmt-vQAfun9YX{>`E5yMz!u_F{f|~=M?rqQcz_&A0?|W zOed*!wA(+-B$-lLCP^Pg0ySz&>c)!+7T&3DE2s_>` zJL_dcjOrenP~7Ot9Dxau;OUbrT+a826wbjJ3yYsZD2lGu6w} zwiOxM3K{>h&RWnFRau)WwXtH{O_>`=*iD%m0JI@%n{~ssXu`H=Oc;MIZCjPGt&(l4 zAWcigF%YC_8z4=q>cazNRX$By-dzUuPhy*%^aV3<-9@)K>Fd=st?TsHy*6mCV_Mgn zudm1b8>rUx=C2U6zj88dRmQL8P;FI4MIV;$3E;+nF+-Rqg8@#PV3? zO_w<&*mG57lsTmK;fCpaqEo$_V$mvya-V*f*#{}oN0|98m89PV)wzCHKP{fnKMIEO zwYAEsi~?nf^*A;9ye74Y#zDrW742!YD?EdS4M_u5hlUyMuF4{Y%1TqaMmyT=0X54R zN*;KUI!p-*XI#aoh2A?&*^aJE8YZD~7U7nH4U6g7p%3BvxcI%h^p z>#olJvMRf@?&_0YJ}LKZ&*>SvBZr_epsJdj5n8lnDvkm)3g$rjK9>Eu6jIE^|)NM=`ZacZ~5}E^wXO% zPj8Y}Zz53Yngm9xw!!UaSPJuEKKu5gLDIZ@${Z4EWtRkk7q(y5?(6jR`pU-G?VEhv zJ~Hchc0;g=*5)*em&BU%9+dp278;)QlE*{Rv3v_SutHu<%f#N&$8m)w#!zD7LW)zH zWQ0;oH0BeDW!oXo7#nHMu%UcuEZ&-A>(>Mw!M&b&mF7F%v&kX zdt9FPc*gBbnRB|L61Jhai+*qWt?ezx1xLhZ8#wK|7%=5C7AskWO=S6+Sf@4V6f%0&Mw>Ha;L{ynlQly-$Ou29+;$~Z$g zMA^Hkn{!xs$=39oZJ9aSl4KAv^YIluY!&GKU3H}p3f z|I7O2zoy;&8F#>f8b}d*1!Uv+RxsXcibQsFou8>`L*(s=~JL z-tNN&9~8HW`zlp9p3uy!1oh8iYd~gu*=HocxnEgn-xKs#j+SO$t^RA9&G!WTbuHst zVE%dm41B$qf;NlWPcXhU#;?~>zBNX_hr!=&2#|jkAo3R=o9xk%HmhpmegnDLfPTX0 z>$LOoSucG5fU&_Pgoh!p@MXMe4Fi!EfT)Pe2A>AO{ZJsFSOS4)oJ&NYZ3_erC4!Os zh%pf0;-Nr5fc!STHO4WsVgu<8hoZc+Kh6UNzbvYiwZB{1M;X=T c7>|V+G30hogB0b?q004r-2Y&PQB3Lo0r?MYX#fBK diff --git a/py-client/libs/__pycache__/overview.cpython-311.pyc b/py-client/libs/__pycache__/overview.cpython-311.pyc index 8ae6cf72e36daf580279396ea752e22d1c818f35..2d13030065a1ac1809f5425a9a5dff3bd58fbac3 100644 GIT binary patch delta 397 zcmdnRyOM`*IWI340|Nttw)ecOewK-RZHyBpPJO}{I=PBb+L#q20|8mgFjfj%4RaPZ zj90^)#e>A=nry%%KKVbRin<_7G=;s2m4RUyCj-N3PM8=YLr+)=V=#jz$K*1mi@c=~ z3=9m>PbaK@+O;Bfaw2m8`^yvt1_n)`$(xxoCcCg`7;@zoq~^sJ6lEr--r@walkQL|MRQq>xhk8kUKr+{jz5w?B`U!d+MM@}`dL=QqaiRd6#Hp5dABxPTpie}pO%OBiUV0ZTrUk|DU$XnqiJylnigIDlf#rf9?5DX z(?fYnud&-VPcxP&&S05hd;ypLMCvZfFPQ-RnHb``_TVqXJPY6#zyG|US~d59pVQyi Ooux%0#`qshW`6^o;(l5H diff --git a/py-client/libs/orderbook.py b/py-client/libs/orderbook.py index 5adef1b..8f3b689 100644 --- a/py-client/libs/orderbook.py +++ b/py-client/libs/orderbook.py @@ -60,6 +60,7 @@ CREATE INDEX IF NOT EXISTS idx_deals_date_time ON deals (trade_date); # SQL is assembled once; order_local_id is derived from the SDK remark property. POSITION_FIELDS = tuple(field.name for field in fields(PositionItem)) DEAL_FIELDS = tuple(field.name for field in fields(DealItem)) + ('order_local_id',) +POSITION_DEFAULTS = asdict(PositionItem()) POSITION_UPSERT = ( f"INSERT INTO positions ({', '.join(POSITION_FIELDS)}) " f"VALUES ({', '.join(':' + key for key in POSITION_FIELDS)}) " @@ -98,20 +99,17 @@ class OrderBook: self.positions = positions self.deals = deals self.deals_sys_ids = set(deals) - self._deal_count = len(deals) - - @staticmethod - def _insert_deals(db: sqlite3.Connection, deals: list[dict]) -> None: - db.executemany(DEAL_INSERT, deals) @staticmethod def deal_record(deal: DealItem) -> dict: if not deal.order_sys_id or deal.volume <= 0: raise ValueError('System order ID and positive volume are required') - if not deal.local_order_id: - raise ValueError('Local order ID is required') + row = asdict(deal) - row['order_local_id'] = deal.local_order_id + row['order_local_id'] = deal.get_local_order_id() + if not row['order_local_id']: + raise ValueError('Local order ID is required') + if any(isinstance(value, float) and not math.isfinite(value) for value in row.values()): raise ValueError('Numeric values must be finite') amount = deal.trade_amount if deal.trade_amount > 0 else deal.price * deal.volume @@ -125,35 +123,38 @@ class OrderBook: return row def sync_deals(self, deals: list[DealItem]) -> None: - new_deals = [] - seen = self.deals_sys_ids.copy() + new_deals = {} for deal in deals: - if deal.order_sys_id in seen: - continue - new_deals.append(self.deal_record(deal)) - seen.add(deal.order_sys_id) + if deal.order_sys_id not in self.deals_sys_ids and deal.order_sys_id not in new_deals: + new_deals[deal.order_sys_id] = self.deal_record(deal) if not new_deals: return with closing(self._connect()) as db, db: - self._insert_deals(db, new_deals) + db.executemany(DEAL_INSERT, new_deals.values()) self.load() def sync_positions(self, positions: list[PositionItem]) -> None: """Replace the complete position snapshot, retaining IDs for existing stocks.""" - self.save({item.stock_code: asdict(item) for item in positions}, list(self.deals.values())) + self.save({item.stock_code: asdict(item) for item in positions}) - def save(self, items: dict, deals: list[dict]) -> None: - if len(deals) < self._deal_count: - raise ValueError('Execution history is append-only') - new_deals = deals[self._deal_count:] - positions = [{**asdict(PositionItem()), **item} for item in items.values()] + def save(self, items: dict, deals: list[dict] | None = None) -> None: + """保存持仓快照,可同时追加成交;省略 deals 时仅更新持仓。""" + new_deals = [] + if deals is not None: + if len(deals) < len(self.deals): + raise ValueError('Execution history is append-only') + new_deals = deals[len(self.deals):] + positions = [{**POSITION_DEFAULTS, **item} for item in items.values()] for row in [*positions, *new_deals]: if any(isinstance(value, float) and not math.isfinite(value) for value in row.values()): raise ValueError('Numeric values must be finite') with closing(self._connect()) as db, db: - for row in db.execute('SELECT stock_code FROM positions').fetchall(): - if row['stock_code'] not in items: - db.execute('DELETE FROM positions WHERE stock_code = ?', (row['stock_code'],)) + removed = [ + (row['stock_code'],) + for row in db.execute('SELECT stock_code FROM positions') + if row['stock_code'] not in items + ] + db.executemany('DELETE FROM positions WHERE stock_code = ?', removed) db.executemany(POSITION_UPSERT, positions) - self._insert_deals(db, new_deals) + db.executemany(DEAL_INSERT, new_deals) self.load() diff --git a/py-client/sdk/__pycache__/models.cpython-311.pyc b/py-client/sdk/__pycache__/models.cpython-311.pyc index 7e15380a5551a4ae47ee4b1a97a7f29e465b018b..dca7610f52338a9de4821d27321559bf2abc3f2b 100644 GIT binary patch literal 12606 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 AnE(I) literal 21776 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

#7s6M1gog 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 mWkHOhA{ str: + def get_local_order_id(self) -> str: return self.remark.split("|", 1)[0] @property @@ -68,7 +68,7 @@ class DealItem: return _side(self.offset_flag) @property - def local_order_id(self) -> str: + def get_local_order_id(self) -> str: return self.remark.split("|", 1)[0] diff --git a/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc b/py-client/strategy/trend/__pycache__/positions.cpython-311.pyc index 8225d9332dc4e93c1a0648a1c5845f54f2b76ad3..a9fa5e9b280bf8909b4533cb26528918aa139c80 100644 GIT binary patch delta 1064 zcmZXST}V@57{{OY%$)2PIP8XGjpPOmXr0eVM2>ll1Aia zxlpdGk5*!w{zOugkuaeui4pl(E^6AbVVuoqQII*Am9^u#j3eu1lbpS*19-aQ5r~t; z*>Vj;UG$u;#FU>&7IWyFu9RPzf@#fpm?9!{gWHmLrkf$vTjW4Y0|1|{-T3>bu?7I> z>j+22qGREZvm)Z`N6-$#KKjnkN(yM9akbodroFq{*VF3h>P{Lw)5C#_n4L5PGSbb{ zZ^j6hWFt|j$3Gh30l-N|OqCU<0l)?Tkr4)99#R72+f&d&wA`l31$~M+nOHGBBm?=@ z1+T&v-frCB-RrztDYD1eIIH9o-8=HYfA{D{j%z)~rMh3T`NbARXj6m&MaWYG>qntn z5v+<(q6m&nUT@}pfZoid5Sxf!KP~jRx%pr#gPqg;BTfLg-c;ZP=B2%f@dERz^mvIE zm^Ikzb!peCh}Wg1g0nc`;XGNa2k*C@#x3KdmTp_FkUBb_dy1_`yPdA*mKu+tM1&IC zxfWf18^-A}H3`u{%WQ{gI|0C5m^6(BqCUSU`a-c_QZp8cN^0UL03 z#%;xowJ3WLeF%JWQXOU+hGH|mOa94NKa$rGI26qx?_vA6eLx=3`wQ4`3e|Q*Y@QsOXM#6(sHyUBoY0~9g=px?G z&-QB52!=t#C@pdf+5*^icm5=fA>PuPj^8!v!R4V>g+S$IrCqb2Td*@8q%WM0nh#_A z@6_<|sW+0|i@GAUO$iRz5xCPWeM2xT#wG)e(&fZbX%?||5W=P4KaSAVvI~CzItTCM delta 1018 zcma))%}*0S6u{qX+ufGh(k@#{C~RAcV2u(W)dM6bAdOP6YEAq=Qa-v$m(t2^E091! zqETW@#EeD{hJ(gvR1T&m<3)|(;K7R=nno}F1C}TW+|1kB#-Jw7;WuyI*SvZ2KJ`8g zTAx@f6#xLfZx7_VbuX=Z^-dE2=m5y~3p#*%FvlE*B{K9PdqO|MG|U-eWWsvngztAezDvHxqZ#`MahP`@H Q6CuP}fIpa^6FbL$0?|m}Qvd(} diff --git a/py-client/strategy/trend/positions.py b/py-client/strategy/trend/positions.py index 16dea12..3169d83 100644 --- a/py-client/strategy/trend/positions.py +++ b/py-client/strategy/trend/positions.py @@ -85,24 +85,21 @@ def manage_positions( elif runtime.account_cfg.enable_loss_add_position: loss_add_action = "大盘信号不允许" - if pnl_rate >= 0: - log.info( - "[Position ↑ ] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", - code, - position.stock_name, - pnl_rate, - profit_action, - loss_add_action, - ) - else: - log.info( - "[Position ↓ ] 代码=%s,名称=%s,盈亏=%.2f%%,止盈=%s,补仓=%s", - code, - position.stock_name, - pnl_rate, - profit_action, - loss_add_action, - ) + strTag = "-" + if pnl_rate >= minimum_profit: + strTag = "↑" + elif pnl_rate< LOSS_TIERS[0]: + strTag = "↓" + + log.info( + "[Position %s ] %s %s,盈亏=%.2f%%,止盈=%s,补仓=%s", + strTag, + code, + position.stock_name, + pnl_rate, + profit_action, + loss_add_action, + ) except Exception: log.exception( "[Position] 持仓处理异常,代码=%s,继续处理后续持仓", diff --git a/py-client/strategy/zt/__pycache__/state.cpython-311.pyc b/py-client/strategy/zt/__pycache__/state.cpython-311.pyc index 996f1a3ee6237c228effe3dbe5de221c7afc3547..9423dcfaa870cd7aec076e4ab8af6dd89c727e8f 100644 GIT binary patch delta 2918 zcmZ`*du&tJ8UK#ozSq9Ke#Lf(6UVVlZb+cT1_4beBvI&^2ahni2f=t;LotrMo|sIq z<0hLrEo0GedomGK?RL8%mX1jcqS{OQgMTK`Kc?Ezm123KTBk{?)M;`wHcgr|P3L-c z$TY63U(Wr$?|$ceuiweW8G1(eiQUct08CB&AoEuHJ>f&nx{3g90Re@6!g=Up?x?Gv zXC{q@=ww3x=%llalZ|tL4-k~m(UZK}u4|c~jGn&A@7UM+j2H<@w)6!{(-MH7q_O#y z`y4?Tljh6Rlo6CMGhb5XjvrtXU73!4jKQv#4PJ#9atlTn~$NKn#BQ?^rs z*be|T(_B7#btYZ26>v&UCsQ-|tGPmr&tJSan=T|TW>c3WT}`()QPU+3PD&ge1^_J5 zzu0b!RRCZC>L#$-ZgMxcQewrkl2rq{DwclL(qFdpSKHcG4lL&sdG)XwJG6LaQU8b+ z77L{b)e)}nJu2U$kTM@H^Ktqs`)dZGw)fNLgfF7n{qGAZGM^}#iB+-FPdG3A$Yl@9 zraL--yR9q~f~}x{m}PULTzc6uM}Hv>4xA)t1g2?`BV5MOv@G(3Cy;67Z4PF6!eyK^ z@VYBAv zug+kgwKw4h*;jngvb0RBib&rLh3TlvdA?;ahj16M%cd)uI~*u%_iN{2dq$p&tl@oW zH!+UD^ruDh6FPd&&dQh)9HFJFU9|j*g~%u8n{aZ0zVc!M8$HI$8MK2u!yZ1p-Rr zP#=0isEfWEicrDJdyh1o07L+{AvV0-n)WwAo=$teWzAzbjgzz2X6a|%U-Mdnb6R85 zdu4T&H?G;r>1-i| zSw`>#gGqYFe+1R&pZ%XYhRSV2i`I%|ShWn7EyMKVK-cG`{`Y-9^{u(r&Z^H2JvdsC zMpbF_QM7l}y*jN*&sCy>YIN{{tsEUMN5@OUE0*Pn(nNXcO!?)cI(5E$>ini&*XJtf zOT#NR)f26Vv9cJuf2`eyhC0-N!@uPo#vc-O>}=)8w0dN^;yb7M&Xo*R(Q}J`lV2H8 zdX%ghj#tElDkjQeqT1Q5^u9f_I4Q0Z6*@l<_8(^%JewMA`TEpS_1OUu3E(zhjrtNk9^i&~L zNbjCa&85G~3>YjxUFWd6sy1n@i0WC#|o{@j^DH@4Uu`nhJ%a%I`;I78j z?7Is5k0Mw~6?{!AfQ*gSg*KgHXJ^(a0{bHtP1_Eq#l!f^ zUo;R<9PF%n4CH_AECfpd8Kyw8PHy!o?gW7M5bmTmd){;7Z?Kd0{>_M5;;U@M zDuWL*=wfi30V@%{z~CqYnE|`?B{OFI+L)zlY_*?(MnTVm0DuduTiHJ_p%6u}py?g< z{u+(M_U}X1JgNi3?@TU^lzJa^Nvn}H%P;-vGeZwve0WwJ`BFJ~sr*V-P0p0Na+R)} z+Lfbk#YX2X);)EwSobWBRNcPiL$?mUd02@kL=7h@?tQ9z-{MHs;a((F(O(UAm&1G2 zV0>}1>IiN)deLUknSpttX-M&l)eDu&Bq_z$9ILkzErVI{HZsffE(ad%n! zJre!Pwl{=jVMFX$7keu7-+s^Y9{=)78=mO8CtC6BR6RRcBvB0(N2)gQ=Gcv~6~jup zVvDG@NLl;U^-UA{{?4nSmi&_}Um6Qc(M0b#UQ74anGn-=dT(V1>L3^!u&D==^Yt&+ zbxaT%G`i}r9S9Pca63f2#%LX$0vapfepX30{x(%4FUr!NOY`U^-QV}e7mn*tv=09t NH#Pa=r)V|D{{iEysICA2 delta 3164 zcma)8YitwQ6+U;ycKr7E9XlkkV-sTM1tf7G5RwoB=|Xr0wiL2f#F%YN60gP%6n2bP z-L2%^jk+#368=F|FNz>6{KyKaLRDAg2hy_Is+ZLmNuq=^Fr$Qf|?qm~2U&8%h9PL2P*C4IKcFBGoxw$)iYh zrKGB|rfj8v^u~DZJ3NXhE0Z-FZt761>ii8GR_EjmH@&t5eMQ!DbxC7oCmX<=>VKoc zlX@3Y<7@iUj*@PAE)nID5q2sWEg6#B6dPqDxS+S0xc%gy_5r~0fQB2zO2bE^Uje{- zAgMs3|3v$dHrt!Crg2E<=ktQ&zRGKNnin zc?&u(E*WkrQi8h^Uo@Ua&mRBWC?NV!st*6w?85h$Mmt}}*45mYTD~#-H)en5VIGBH z5~sAhHdcMZl#bW&5HnTY_$nlHyf((*PtDf;rlhZ;2Z&iJGOvwUEAl-A@UVJ;9Pzc{ zPtA67pke{Qs^k^FG#^3j*krNySH0&DtG!19JfthuwXyIza)zufrCwO%HF*<$X>7qM ziy4{lCl(iK#}6!CWWrxt8g$k8^A5aj@u7BXx9&ww{8DSjto1mm$EO%Oer~mSt7pUO z<+NpZV{B7rjJffDtPTC{YCH^YjBL)=vBv5Ecw?lYVmIgDA-}D>pY3E#JdGr3Z5Srq zDI*VgIiy>54{E|*dpA0OPuZ==gS~b?Ha6+-qWwpj#PviZ&aqJrw>W;GKMVksG{b*% zjHm5#66MYLLBYFgW!K82&@)=_gx>>>9C-kh=qu6dhdDDzKT>DqMBGcHBLr*!Fu{>! zxiJER1P0_h^>U;FO7vX(8aF~D&2%DuInK>aCApKtYzTk`ZUTSp+}lvnCX(?>S0b0< zY_z1DPDW=FCDqmV%=~N=yX%jkar}0Dz;~Ru5#N$B8E2=imlTO;bgrb};@1*fh)kZt zkLz2UZ^$NWbS62)4HNZI0>|)Q>W9&9aHs1}>2Sdj&S;A2LxTEHL48QH)@Rfb71UUM zXR&2QMQ4Kqw80`nmKJ@j_xtbmFZV28eYEchD*6Tl-+9vUGMdr&>H(WIP4NBdMUVRf5Mqb2Dhf@#w-A!KY`Q zJDy!A4xADOP8FS}1?TCkLS$^Wb+>f6aNd`n6@J~0Zt zM;@;?^dOD%*bw}B$TQxII~)IPHvoVY0R1xqgny@jhshy4*t9FXSr$}GQAstPs-Zn< zllFKjR##)AuE;Fh(O_y}_zVP4KvPbPW^%fu3^@k@4*@TM76PQ|OR7Y&e=0ej`2Srv zQW^o8JByz+9ZSDmCOa^gEt{}j4=!I$kz*w%*j=K>zoZcZokC!r=xf`R2w+o5mvQnT4Zk`faQFZ4y;oyB>D5FU8hcL#wT!V(T8Eb&upSm@Vt%onFZ= zwhheoMeTYsV=%q~#$c4T!s~yvV7F&XOWF@jZuk|R@%#`CCP|`fJgjyacxnm#81b;#YI#KL7Dib51Hz;gW1KU2aoob-U;2z)JVZ9r z1U6G943lS4G*8zy{Je(5)2-YZPa?$Atg40wYa+M`+zx!A#kH?Sx7E7FkG@9%Jgj~U zAXu0nYvEscx;5u6QUEEGQsB=$jx>)p-PjsANz!-Y+4wfuS*v5~E>XN9qOaKSib(Yk zS@jPPuZUDzA+Ly3+X$z@MlwklRel!UWZ?`1bjLZ;K{ywl_C4qdAg+mw+BRx{ z$QNZ&yE-*9A5D-__INh(?p=JqzY~3i}lx zl@snR?_iOWy`-3lPq7?Xf|HpxOm?K-iNC{WM@;9k-1D z>1A9a2{WLSE2X^qJW#zjKFp8c|Ja2t=v2gaha5hpnM1CS;TVq;QnU;L- z(!esi5_&Wv`1U=SC^82H=3s$2_*!%~-3hL_gRAaf(cK}qJ0wt$pcR_Xhi_!US-*JF zWL