ó
    “ÞjV-  ã                  ó  • S r SSKJr  SSKrSSKrSSKrSSKJr  SSKJ	r	J
r
  SSKJr  SSKJrJr  SS	KJr  SS
KJr  SSKJr  \	 " S S5      5       r\	 " S S5      5       r\	 " S S5      5       r\	 " S S5      5       r " S S5      rg)zBPaper trading engine: simulated maker fills against live book top.é    )ÚannotationsN©Údeque)Ú	dataclassÚfield)ÚPath)ÚListÚOptionalé   )ÚPaperCfg)ÚBookTop)ÚQuotec                  ó\   • \ rS rSr% S\S'   S\S'   S\S'   S\S'   S\S'   S\S	'   S\S
'   Srg)ÚFillé   ÚstrÚidÚfloatÚtsÚsideÚpriceÚsize_btcÚfee_usdÚmid_at_fill© N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__annotations__Ú__static_attributes__r   ó    Úsrc/paper_engine.pyr   r      s&   ‡ àƒGØƒIØ
ƒIØƒLØƒOØƒNØÖr#   r   c                  óR   • \ rS rSr% S\S'   S\S'   S\S'   S\S'   S\S'   S\S	'   S
rg)ÚOpenLoté   r   r   r   r   r   r   Únotional_usdr   r   Nr   r   r#   r$   r&   r&      s!   ‡ àƒGØ
ƒIØƒLØƒOØÓØ†Ir#   r&   c                  óp   • \ rS rSr% S\S'   S\S'   S\S'   S\S'   S\S'   S\S	'   S\S
'   S\S'   S\S'   Srg)ÚClosedTradeé&   r   r   r   r   r   Úentry_priceÚ
exit_pricer   Úpnl_usdr   ÚboolÚ
profitabler   Nr   r   r#   r$   r*   r*   &   s2   ‡ àƒGØƒIØ
ƒIØÓØÓØƒOØƒNØƒNØÖr#   r*   c                  ó\  • \ rS rSr% S\S'   S\S'   SrS\S'   SrS\S'   \" \S9r	S	\S
'   \" \S9r
S\S'   \" \S9rS\S'   \" \R                  S9rS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   \" S S9rS\S'   \" S S9rS\S'   S!S jrS rg)"Ú
PaperStateé3   r   Úequity0Úcash_usdç        Úinventory_btcÚrealized_pnl)Údefault_factoryú
List[Fill]ÚfillszList[OpenLot]Ú	open_lotszList[ClosedTrade]Úclosed_tradesÚday_start_tsÚday_start_equityNúOptional[Quote]ÚquoteÚlast_midÚprev_midÚbuy_notionalÚbuy_qtyÚsell_notionalÚsell_qtyc                 ó   • [        SS9$ )NiX  ©Úmaxlenr   r   r#   r$   Ú<lambda>ÚPaperState.<lambda>G   s	   € ¼ÀcÒ9Jr#   r   Úprice_historyc                 ó   • [        SS9$ )Ni   rI   r   r   r#   r$   rK   rL   H   s	   € ´5ÀÒ3Dr#   Úcandlesc                óJ   • U R                   (       d  U R                  U l         g g ©N)r?   r4   ©Úselfs    r$   Ú__post_init__ÚPaperState.__post_init__J   s   € Ø×$×$Ø$(§L¡LˆDÕ!ð %r#   )r?   )ÚreturnÚNone)r   r   r   r    r!   r7   r8   r   Úlistr;   r<   r=   Útimer>   r?   rA   rB   rC   rD   rE   rF   rG   rM   rO   rT   r"   r   r#   r$   r2   r2   3   s×   ‡ àƒNØƒOØ€M�5ÓØ€L�%ÓÙ¨dÑ3€Eˆ:Ó3Ù$°TÑ:€Iˆ}Ó:Ù',¸TÑ'B€MÐ$ÓBÙ°·	±	Ñ:€L�%Ó:Ø!Ð�eÓ!Ø!€Eˆ?Ó!Ø€HˆeÓØ€HˆeÓà€L�%ÓØ€GˆUÓØ€M�5ÓØ€HˆeÓá Ñ1JÑK€M�5ÓKÙÑ+DÑE€GˆUÓE÷1r#   r2   c                  óü   • \ rS rSrSrSS jrSS jrSS jrSS jrSS jr	            SS jr
SS	 jrSS S jjrSS!S jjrSS!S jjrSS!S jjrSS!S jjrS"S jrS"S jrSS jrSrS#S jrSS jrS$S jrSrg
)%ÚPaperEngineéO   é   c                ó,   • X l         [        XS9U l        g )N)r4   r5   )Úcfgr2   Ústate)rS   Ú
equity_usdÚpapers      r$   Ú__init__ÚPaperEngine.__init__R   s   € ØŒÜ¨
ÑHˆ�
r#   c                ó$   • XR                   l        g rQ   )r`   rA   )rS   Úqs     r$   Ú	set_quoteÚPaperEngine.set_quoteV   s   € Ø�
‰
Õr#   c                ó`  • U R                   nUR                  =(       d    UR                  nUR                  =(       d    UR                  Ul        UR                  Ul        UR	                  5       (       ah  UR                  S:”  aX  [
        R
                  " 5       nUR                  R                  XAR                  S.5        U R                  UR                  U5        [        [        U R                  SS5      =(       d    [        U R                  SS5      5      nU(       a&  UR                  (       a  UR	                  5       (       d  / $ UR                  n/ nUR                  S:”  a\  UR                  UR                  ::  aB  UR                  U R                  SUR                  UR                   UR                  5      5        OdX6R                  s=:”  a  UR                  :¼  aD  O  OAUR                  U R                  SUR                  UR                   UR                  5      5        UR"                  S:”  a\  UR"                  UR$                  :¼  aB  UR                  U R                  SUR$                  UR                   UR                  5      5        OdX6R$                  s=:  a  UR                  ::  aD  O  OAUR                  U R                  SUR$                  UR                   UR                  5      5        ['        [        U R                  S	S
5      =(       d    S
5      nU(       d÷  US:”  añ  UR                   S:”  aá  UR                  U-  S-  n	[)        UR                  UR                  -
  5      U	::  aB  UR                  U R                  SUR                  UR                   UR                  5      5        Og[)        UR$                  UR                  -
  5      U	::  aA  UR                  U R                  SUR$                  UR                   UR                  5      5        U(       a  S Ul        U$ )Nr   )r   ÚmidÚfill_on_touchTÚfills_on_touchFÚbuyÚsellÚnear_fill_bpsr6   ç     ˆÃ@)r`   rC   rj   rB   ÚokrY   rM   ÚappendÚ_update_candler/   Úgetattrr_   rA   ÚaskÚbid_pxÚ_fillr   ÚbidÚask_pxr   Úabs)
rS   ÚtopÚstÚprevÚnowÚfill_okrf   Ú	new_fillsÚnearÚthrs
             r$   Úon_bookÚPaperEngine.on_bookY   sµ  € Ø�Z‰ZˆØ�{‰{×%˜cŸg™gˆØ—k‘k×, S§W¡WˆŒØ—g‘gˆŒØ�6‰6�8‰8˜Ÿ™ !›Ü—)’)“+ˆCØ×Ñ×#Ñ#¨3·w±wÑ$?Ô@Ø×Ñ §¡¨Ô-ä”w˜tŸx™x¨¸$Ó?×mÄ7È4Ï8É8ÐUeÐglÓCmÓnˆÞ˜bŸhŸh¨c¯f©f¯h©hØˆIà�H‰HˆØ "ˆ	ð �7‰7�Q‹;˜3Ÿ7™7 a§h¡hÓ.Ø×Ñ˜TŸZ™Z¨¨q¯x©x¸¿¹ÀSÇWÁWÓMÕNØ—H‘HÕ' §¡Ö'Ø×Ñ˜TŸZ™Z¨¨q¯x©x¸¿¹ÀSÇWÁWÓMÔNà�7‰7�Q‹;˜3Ÿ7™7 a§h¡hÓ.Ø×Ñ˜TŸZ™Z¨°·±¸!¿*¹*ÀcÇgÁgÓNÕOØ—H‘HÕ' §¡Ö'Ø×Ñ˜TŸZ™Z¨°·±¸!¿*¹*ÀcÇgÁgÓNÔOô ”W˜TŸX™X ¸Ó<×CÀÓDˆÞ˜T A›X¨!¯*©*°q«.Ø—'‘'˜D‘. 8Ñ+ˆCÜ�3—7‘7˜QŸX™XÑ%Ó&¨#Ó-Ø× Ñ  §¡¨E°1·8±8¸Q¿Z¹ZÈÏÉÓ!QÕRÜ�Q—X‘X §¡Ñ'Ó(¨CÓ/Ø× Ñ  §¡¨F°A·H±H¸a¿j¹jÈ#Ï'É'Ó!RÔSæØˆBŒHØÐr#   c                óâ  • U R                   R                  nX#-  nXe-  S-  nU R                  nUS:X  aW  U=R                  Xg-   -  sl        U=R                  U-  sl        U=R
                  U-  sl        U=R                  U-  sl        OVU=R                  Xg-
  -  sl        U=R                  U-  sl        U=R                  U-  sl        U=R                  U-  sl        [        [        R                  " 5       R                  S S [        R                  " 5       UUUUUS9n	UR                  R                  U	5        U R!                  U	5         [#        [$        5      R'                  5       R(                  S   S-  S-  n
U
R*                  R-                  SSS	9  U
R/                  S
5       nUR1                  [2        R4                  " U	R6                  U	R8                  U	R:                  U	R<                  U	R>                  [A        U	R<                  U	R>                  -  S5      U	RB                  U	RD                  S.5      S-   5        S S S 5        U	$ ! , (       d  f       U	$ = f! [F         a     U	$ f = f)Nrp   rm   é   )r   r   r   r   r   r   r   r   Údatazfills.jsonlT)ÚparentsÚexist_okÚaé   )r   r   r   r   r   r(   r   r   Ú
)$r_   Úmaker_fee_bpsr`   r5   r7   rD   rE   rF   rG   r   ÚuuidÚuuid4ÚhexrY   r;   rr   Ú_apply_fifor   Ú__file__Úresolverˆ   ÚparentÚmkdirÚopenÚwriteÚjsonÚdumpsr   r   r   r   r   Úroundr   r   Ú	Exception)rS   r   r   Úsizerj   Úfee_bpsÚnotionalÚfeer|   ÚfÚlogÚfhs               r$   rw   ÚPaperEngine._fill‚   sü  € Ø—(‘(×(Ñ(ˆØ‘<ˆØÑ  8Ñ+ˆØ�Z‰ZˆØ�5‹=Ø�KŠK˜8™>Ñ)�KØ×Ò Ñ$ÕØ�OŠO˜xÑ'�OØ�JŠJ˜$ÑŽJà�KŠK˜8™>Ñ)�KØ×Ò Ñ$ÕØ×Ò Ñ(ÕØ�KŠK˜4Ñ�KÜÜ�zŠz‹|×Ñ  Ð$Ü�yŠy‹{ØØØØØñ
ˆð 	�‰�‰˜ÔØ×Ñ˜Ôð	Ü”x“.×(Ñ(Ó*×2Ñ2°1Ñ5¸Ñ>ÀÑNˆCØ�J‰J×Ñ T°DÐÑ9Ø—‘˜#” "Ø—‘Ü—J’Jà"#§$¡$Ø"#§$¡$Ø$%§F¡FØ%&§W¡WØ()¯
©
Ü,1°!·'±'¸A¿J¹JÑ2FÈÓ,JØ'(§y¡yØ+,¯=©=ñ	óð ñô÷ ð$ ˆ÷% ”ð$ ˆûô ó 	ØØˆð	ús2   ÅAI  Æ+BIÉI  É
IÉI  ÉI  É 
I.É-I.c                óB  • U R                   nUR                  nUR                  (       a  UR                  UR                  -  OSnUR                  S:X  Ga©  US:”  Ga2  UR                  (       Ga   UR                  S   R                  S:X  Ga  UR                  S   n[        X5R                  5      nSnXF-  nUR                  UR                  -
  U-  U-
  U-
  n	U R                  XQR                  XiU5        U=R                  U-  sl        UR                  UR                  -  Ul        X6-  nUR                  S::  a  UR                  R                  S5        US:”  a1  UR                  (       a   UR                  S   R                  S:X  a  GM  US:”  ai  UR                  R                  [        [        R                  " 5       R                  SS SUR                  UUR                  U-  UR                  S	95        ggUS:”  Ga+  UR                  (       Ga  UR                  S   R                  S:X  aü  UR                  S   n[        X5R                  5      nXF-  nUR                  UR                  -
  U-  U-
  n	U R                  XQR                  XiU5        U=R                  U-  sl        UR                  UR                  -  Ul        X6-  nUR                  S::  a  UR                  R                  S5        US:”  a0  UR                  (       a  UR                  S   R                  S:X  a  Mü  US:”  ai  UR                  R                  [        [        R                  " 5       R                  SS SUR                  UUR                  U-  UR                  S	95        gg)
zLMatch fill against opposite open lots FIFO; leftover becomes a new open lot.r6   rm   çê-�™—q=r   ÚshortNé
   Úlong©r   r   r   r   r(   r   )r`   r   r   r   r<   Úminr   Ú_record_closer(   Úpoprr   r&   rŽ   r�   r�   r   )
rS   r    r|   Ú	remainingÚfee_per_btcÚlotÚ	closed_szÚentry_fee_shareÚexit_feeÚpnls
             r$   r‘   ÚPaperEngine._apply_fifo³   s×  € à�Z‰ZˆØ—J‘Jˆ	Ø23·*·*�q—y‘y 1§:¡:Ò-À#ˆà�6‰6�UŒ?à˜eÔ#¨¯¯¨¸¿¹Àa¹×9MÑ9MÐQXÔ9XØ—l‘l 1‘o�Ü 	¯<©<Ó8�	à"%�Ø&Ñ2�Ø—y‘y 1§7¡7Ñ*¨iÑ7¸(ÑBÀ_ÑT�Ø×"Ñ" 3¯©°ÀÔJØ—’ 	Ñ)•Ø#&§9¡9¨s¯|©|Ñ#;�Ô ØÑ&�	Ø—<‘< 5Ó(Ø—L‘L×$Ñ$ QÔ'ð ˜eÓ#¨¯¯¸¿¹Àa¹×9MÑ9MÐQXÖ9Xð ˜5Ó Ø—‘×#Ñ#ÜÜŸ:š:›<×+Ñ+¨C¨RÐ0Ø#ØŸg™gØ!*Ø%&§W¡W¨yÑ%8ØŸ4™4ñõ	ð !ð ˜eÔ#¨¯¯¨¸¿¹Àa¹×9MÑ9MÐQWÓ9WØ—l‘l 1‘o�Ü 	¯<©<Ó8�	Ø&Ñ2�Ø—w‘w §¡Ñ*¨iÑ7¸(ÑB�Ø×"Ñ" 3¯©°ÀÔJØ—’ 	Ñ)•Ø#&§9¡9¨s¯|©|Ñ#;�Ô ØÑ&�	Ø—<‘< 5Ó(Ø—L‘L×$Ñ$ QÔ'ð ˜eÓ#¨¯¯¸¿¹Àa¹×9MÑ9MÐQWÕ9Wð ˜5Ó Ø—‘×#Ñ#ÜÜŸ:š:›<×+Ñ+¨C¨RÐ0Ø$ØŸg™gØ!*Ø%&§W¡W¨yÑ%8ØŸ4™4ñõ	ð !r#   c                óŒ  • U R                   n[        [        R                  " 5       R                  S S [
        R
                  " 5       UR                  UR                  UUUUUS:„  S9	nUR                  R                  U5        [        UR                  5      S:”  a  UR                  SS  Ul        U=R                  U-  sl        g )Nr§   r   )	r   r   r   r,   r-   r   r.   r   r0   éÈ   i8ÿÿÿ)r`   r*   rŽ   r�   r�   rY   r   r   r=   rr   Úlenr8   )rS   r¯   r-   rœ   r³   rŸ   r|   Úcts           r$   r«   ÚPaperEngine._record_closeì   s£   € ð �Z‰ZˆÜÜ�zŠz‹|×Ñ  Ð$Ü�yŠy‹{Ø—‘ØŸ	™	Ø!ØØØØ˜Q‘wñ

ˆð 	×Ñ×Ñ Ô#Üˆr×ÑÓ  3Ó&Ø!×/Ñ/°°Ð6ˆBÔØ
�Š˜3ÑŽr#   c                ó   • / nU R                   R                   Ha  nUR                  UR                  UR                  UR
                  UR                  [        UR                  S5      UR                  S.5        Mc     U$ )Nr‹   r©   )
r`   r<   rr   r   r   r   r   rš   r(   r   )rS   Úoutr¯   s      r$   Úopen_positionsÚPaperEngine.open_positions   sf   € ØˆØ—:‘:×'Ô'ˆCØ�J‰JàŸ&™&ØŸH™HØ ŸY™YØ #§¡Ü$)¨#×*:Ñ*:¸AÓ$>ØŸ&™&ñö	ñ (ð ˆ
r#   Nc                óN  • Ub  UOU R                   nU R                  R                  U* S  nU Vs/ s Hh  nUR                  [	        UR
                  S5      UR                  UR                  UR                  UR                  UR                  UR                  S.PMj     sn$ s  snf )Né   )r   r.   r   r   r0   r   r,   r-   )ÚMAX_CLOSE_EVENTSr`   r=   r   rš   r.   r   r   r0   r   r,   r-   )rS   ÚnÚrecentÚcs       r$   Úclose_eventsÚPaperEngine.close_events  s—   € Ø‘‰A D×$9Ñ$9ˆØ—‘×)Ñ)¨1¨"¨#Ð.ˆñ ó
ò �ð —d‘dÜ  §¡¨AÓ.ØŸJ™JØ—d‘dØŸl™lØŸ™Ø Ÿ}™}ØŸl™lô	ñ ñ
ð 	
ùò 
s   °A/B"c                ó˜   • Ub  UOU R                   R                  nU R                   R                  U R                   R                  U-  -   $ rQ   )r`   rB   r5   r7   )rS   rj   Úms      r$   ÚequityÚPaperEngine.equity   s;   € Ø‘?‰C¨¯
©
×(;Ñ(;ˆØ�z‰z×"Ñ" T§Z¡Z×%=Ñ%=ÀÑ%AÑAÐAr#   c                óR   • U R                  U5      U R                  R                  -
  $ rQ   )rÈ   r`   r4   ©rS   rj   s     r$   Ú
unrealizedÚPaperEngine.unrealized$  s    € Ø�{‰{˜3Ó $§*¡*×"4Ñ"4Ñ4Ð4r#   c                óR   • U R                  U5      U R                  R                  -
  $ rQ   )rÈ   r`   r?   rË   s     r$   Úday_pnlÚPaperEngine.day_pnl'  s    € Ø�{‰{˜3Ó $§*¡*×"=Ñ"=Ñ=Ð=r#   c                ó¤   • U R                   R                  =(       d    U R                   R                  nUS::  a  gSU R                  U5      -  U-  $ )Nr   r6   g      Y@)r`   r?   r4   rÏ   )rS   rj   Úbases      r$   Úday_pnl_pctÚPaperEngine.day_pnl_pct*  sC   € Ø�z‰z×*Ñ*×@¨d¯j©j×.@Ñ.@ˆØ�1‹9ØØ�t—|‘| CÓ(Ñ(¨4Ñ/Ð/r#   c                ón   • U R                   nUR                  S::  a  g UR                  UR                  -  $ ©Nr¥   )r`   rE   rD   ©rS   r|   s     r$   Ú
avg_buy_pxÚPaperEngine.avg_buy_px0  s-   € Ø�Z‰ZˆØ�:‰:˜ÓØØ�‰ §¡Ñ+Ð+r#   c                ón   • U R                   nUR                  S::  a  g UR                  UR                  -  $ rÖ   )r`   rG   rF   r×   s     r$   Úavg_sell_pxÚPaperEngine.avg_sell_px6  s/   € Ø�Z‰ZˆØ�;‰;˜%ÓØØ×Ñ "§+¡+Ñ-Ð-r#   c                ó@   • [        U R                  R                  5      $ rQ   )rX   r`   rM   rR   s    r$   Úprice_history_listÚPaperEngine.price_history_list<  s   € Ü�D—J‘J×,Ñ,Ó-Ð-r#   i,  c                ó0  • [        X R                  -  5      U R                  -  nU R                  R                  nU(       a  [        US   S   5      U:w  a  UR	                  [        U5      XXS.5        g US   nXS   :”  a  XS'   XS   :  a  XS'   XS'   g )NéÿÿÿÿÚt)râ   ÚoÚhÚlrÃ   rä   rå   rÃ   )ÚintÚ
CANDLE_SECr`   rO   rr   r   )rS   rj   r   ÚbucketrO   rÃ   s         r$   rs   ÚPaperEngine._update_candleA  sˆ   € Ü�RŸ?™?Ñ*Ó+¨d¯o©oÑ=ˆØ—*‘*×$Ñ$ˆÞœ#˜g b™k¨#Ñ.Ó/°6Ó9Ø�N‰N¤ v£°SÈÑWÕXà˜‘ˆAØ�s‘V‹| c˜s™VØ�s‘V‹| c˜s™VØˆcŠFr#   c                ó@   • [        U R                  R                  5      $ rQ   )rX   r`   rO   rR   s    r$   Úcandles_listÚPaperEngine.candles_listL  s   € Ü�D—J‘J×&Ñ&Ó'Ð'r#   c                ó@   • [        U R                  R                  5      $ rQ   )r·   r`   r;   rR   s    r$   Úfills_todayÚPaperEngine.fills_todayO  s   € Ü�4—:‘:×#Ñ#Ó$Ð$r#   )r_   r`   )ra   r   rb   r   )rf   r@   rV   rW   )r{   r   rV   r:   )
r   r   r   r   rœ   r   rj   r   rV   r   )r    r   rV   rW   )r¯   r&   r-   r   rœ   r   r³   r   rŸ   r   rV   rW   )rV   ú
List[dict]rQ   )rÁ   z
int | NonerV   rð   )rj   úOptional[float]rV   r   )rV   rñ   )rj   r   r   r   rV   rW   )rV   ræ   )r   r   r   r    rÀ   rc   rg   rƒ   rw   r‘   r«   r¼   rÄ   rÈ   rÌ   rÏ   rÓ   rØ   rÛ   rÞ   rç   rs   rë   rî   r"   r   r#   r$   r[   r[   O   sž   † ØÐôIôô'ôR/ôb7ðrØðØ(-ðØ5:ðØAFðØMRðà	ôô(ö
ö"Bö5ö>ö0ô,ô.ô.ð €Jô	ô(÷%r#   r[   )Ú__doc__Ú
__future__r   r˜   rY   rŽ   Úcollectionsr   Údataclassesr   r   Úpathlibr   Útypingr	   r
   Úconfigr   Úmarket_datar   Úquoterr   r   r&   r*   r2   r[   r   r#   r$   Ú<module>rû      s™   ðÙ HÝ "ã Û Û Ý ß (Ý ß !å Ý  Ý ð ÷ð ó ðð ÷ð ó ðð ÷	ð 	ó ð	ð ÷1ð 1ó ð1÷6A%ò A%r#   