
    'i                     .   d dl mZmZmZmZ d dlZd dlmZ d dlmZmZm	Z	 d dl
Z
d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlmZmZ d dlmZ d dlmZmZmZmZmZ d d	lm Z m!Z! eZdd
Z" G d de#      Z$ G d de      Z%d Z& G d d ee%e#            Z'y)    )absolute_importdivisionprint_functionunicode_literalsN)copy)datedatetime	timedelta)Contract)	TimeFramePosition)
MetaParams)bytesbstrqueuewith_metaclasslong)AutoDictUTCc                     | st        j                         S t        t        |       d      \  }}|dz  }t        j                  |      j                  |      S )Ni  )microsecond)r	   utcnowdivmodr   utcfromtimestampreplace)tstampsecmsecusecs       W/var/www/app/trading-bot/venv/lib/python3.12/site-packages/backtrader/stores/ibstore.py_ts2dtr!   ,   sN      tF|T*IC$;D$$S)11d1CC    c                   @    e Zd ZdZdefdefdefdefdefdefgZd
d	Z	y)RTVolumezParses a tickString tickType 48 (RTVolume) event from the IB API into its
    constituent fields

    Supports using a "price" to simulate an RTVolume from a tickPrice event
    pricesizer	   volumevwapsingleNc           
          t        |j                  d            }| j                  D ]*  \  }}t        | ||r |t	        |            n |              , ||| _        || xj                  |z  c_        y y )N;)itersplit_fieldssetattrnextr%   r	   )selfrtvolr%   tmoffsettokensnamefuncs          r    __init__zRTVolume.__init__E   ss    ekk#&' ,, 	IJD$D$eT&\ 2H	I DJMMX%M  r"   ) NN)
__name__
__module____qualname____doc__floatintr!   boolr.   r7    r"   r    r$   r$   6   sB     
%		V	3		4G&r"   r$   c                   ,     e Zd ZdZ fdZ fdZ xZS )MetaSingletonz1Metaclass to make a metaclassed class a singletonc                 >    t         t        |   |||       d | _        y N)superrB   r7   
_singleton)clsr5   basesdct	__class__s       r    r7   zMetaSingleton.__init__W   s    mS*4<r"   c                 d    | j                   t        t        |   |i || _         | j                   S rD   )rF   rE   rB   __call__)rG   argskwargsrJ   s      r    rL   zMetaSingleton.__call__[   s4    >>!mS2DCFC N ~~r"   )r9   r:   r;   r<   r7   rL   __classcell__rJ   s   @r    rB   rB   U   s    ; r"   rB   c                     d| _         | S )NT)_ibregister)fs    r    
ibregisterrT   d   s    AMHr"   c            	           e Zd ZdZdZdZdZdZed        Z	ed        Z
 fdZdJdZd	 Zd
 Zd Zd ZdKdZd Zd Zd Zed        Zed        Zed        Zd Zed        Zd Zd Zed        Zd Zd ZdLdZ dLdZ!d Z"dMdZ#d Z$ed         Z%ed!        Z&	 	 dNd"Z'	 dOd#Z(d$ Z)dPd%Z*d& Z+dMd'Z,d( Z-ed)        Z.ed*        Z/ed+        Z0ed,        Z1 e2g d-      Z3e4jj                  d.fe4jl                  d.fe4jl                  d.fe4jl                  d/fe4jl                  d/fe4jn                  d.fe4jp                  d.fe4jr                  d.fd0Z:e4jj                  e4jn                  e4jp                  e4jr                  e4jv                  d1Z<d2 Z=d3 Z>d4 Z?d5 Z@d6 ZAd7 ZBd8 ZC	 dQd9ZDd: ZEd; ZFed<        ZGed=        ZHed>        ZIed?        ZJd@ ZKedA        ZLdRdBZMedC        ZNedD        ZOdLdEZPedF        ZQdMdGZRdMdHZSdMdIZT xZUS )SIBStorea%  Singleton class wrapping an ibpy ibConnection instance.

    The parameters can also be specified in the classes which use this store,
    like ``IBData`` and ``IBBroker``

    Params:

      - ``host`` (default:``127.0.0.1``): where IB TWS or IB Gateway are
        actually running. And although this will usually be the localhost, it
        must not be

      - ``port`` (default: ``7496``): port to connect to. The demo system uses
        ``7497``

      - ``clientId`` (default: ``None``): which clientId to use to connect to
        TWS.

        ``None``: generates a random id between 1 and 65535
        An ``integer``: will be passed as the value to use.

      - ``notifyall`` (default: ``False``)

        If ``False`` only ``error`` messages will be sent to the
        ``notify_store`` methods of ``Cerebro`` and ``Strategy``.

        If ``True``, each and every message received from TWS will be notified

      - ``_debug`` (default: ``False``)

        Print all messages received from TWS to standard output

      - ``reconnect`` (default: ``3``)

        Number of attempts to try to reconnect after the 1st connection attempt
        fails

        Set it to a ``-1`` value to keep on reconnecting forever

      - ``timeout`` (default: ``3.0``)

        Time in seconds between reconnection attemps

      - ``timeoffset`` (default: ``True``)

        If True, the time obtained from ``reqCurrentTime`` (IB Server time)
        will be used to calculate the offset to localtime and this offset will
        be used for the price notifications (tickPrice events, for example for
        CASH markets) to modify the locally calculated timestamp.

        The time offset will propagate to other parts of the ``backtrader``
        ecosystem like the **resampling** to align resampling timestamps using
        the calculated offset.

      - ``timerefresh`` (default: ``60.0``)

        Time in seconds: how often the time offset has to be refreshed

      - ``indcash`` (default: ``True``)

        Manage IND codes as if they were cash for price retrieval
    i   N)
)hostz	127.0.0.1)portiH  )clientIdN)	notifyallF)_debugF)	reconnect   )timeoutg      @)
timeoffsetT)timerefreshg      N@)indcashTc                 &     | j                   |i |S )z%Returns ``DataCls`` with args, kwargs)DataClsrG   rM   rN   s      r    getdatazIBStore.getdata   s     s{{D+F++r"   c                 &     | j                   |i |S )zAReturns broker with *args, **kwargs from registered ``BrokerCls``)	BrokerClsrd   s      r    	getbrokerzIBStore.getbroker   s     s}}d-f--r"   c                     t         t                   t        j                          _        t        j                          _        t        j                          _        t        j                          _        t        j                          _
        t        j                          _        d _        d  _        d  _        t                _        d _        t        j                          _        t'                _        t+        j,                          _        t+        j,                          _        t3                _        t3                _        t3                _        t3                _        t3                _        t?                _         t?                _!        t?                _"        d _#        t+        jH                  tJ               _&        tO        jP                   jR                         _*        d  _+        t+        jH                  t               _,        t                _-        t]        j^                          _0         jb                  jd                  )tg        jh                  dtk        dd      dz
         _2        n jb                  jd                   _2        tm        jn                   jb                  jp                   jb                  jr                   jd                         _:         jb                  jv                  s jb                  jx                  r% jt                  j{                   j|                         t        j                   t~        j                        }|D ]I  \  }}t        |dd      st        tl        j                  |      } jt                  j                  ||       K  fd} fd	}t+        jH                  t               _E         j                  j                         D ]0  \  }}|D ]&  }	 j                   ||	         j                  |       ( 2  j                  D ]!  }	 j                  |	   j                  |
       # y )NFr            )rW   rX   rY   rR   c                 n    | j                         \  }}j                  |   \  }}|t        |      |z  fS rD   )r-   _sizesr>   )xnttfcompr1   s        r    keyfnzIBStore.__init__.<locals>.keyfn  s6    779DAq{{1~HBA&&r"   c                 b    | j                         \  }}j                  |   }|t        |      fS rD   )r-   _dur2tfr>   )ro   rp   drr   r1   s       r    key2fnz IBStore.__init__.<locals>.key2fn  s-    779DAqaBA<r"   )key)JrE   rV   r7   	threadingLock_lock_q_lock_accupd	_lock_pos_lock_notifEvent_event_managed_accounts_event_accdownloaddontreconnect_envbrokerlistdatasccount_lock_tmoffsetr
   r3   collectionsOrderedDictqstsdictiscash	histexreqhistfmthistsendhisttzr   acc_cash	acc_valueacc_updsport_updatedefaultdictr   	positions	itertoolscount	REQIDBASE	_tickerIdorderidcdetailsmanaged_accountsr   QueuenotifsprY   randomrandintpowiboptibConnectionrW   rX   connr[   rZ   registerAllwatcherinspect
getmembersismethodgetattrmessageregisterrevdur
_durationsitemsappendsort)r1   methodsr5   methodr   rt   rx   durationbarsizesbarsizerJ   s   `         r    r7   zIBStore.__init__   s   gt%' ~~'%NN,")$>>+ (1'8$"+//"3"	V
'nn.! ))+))+fvf 
! 
 $00:"8#//5 $kkm 66??""NN1c!Rj1n=DM FFOODM &&466;;H	 66==DFF,,II!!$,,/ $$T7+;+;<# 	0LD&6=%8emmT2GIIvw/	0	'	  "--d3
 #'//"7"7"9 	=Hh# =E'N+228<=	= {{ 	2GKK %%&%1	2r"   c                     | j                  d       |>|j                  | _        | j                  j                  |       | j	                  d      S ||| _        y y )NT)	fromstartstart)r\   r   r   r   getTickerQueuer   )r1   datar   s      r    r   zIBStore.start,  s]    & 		DIJJd# &&T&22 DK  r"   c                     	 | j                   j                          | j                  j	                          | j
                  j	                          y # t        $ r Y @w xY wrD   )r   
disconnectAttributeErrorr   setr   r1   s    r    stopzIBStore.stop<  sQ    	II  "
 	$$((*##%  		s   A 	AAc                 B    | j                   j                  r	t        |  y y rD   )r   r[   print)r1   rM   s     r    logmsgzIBStore.logmsgF  s    66==4L r"   c                     | j                  t        |             | j                  j                  rM| j                  j                  |t        |j                               t        |j                               f       y y rD   )
r   strr   rZ   r   puttuplevaluesr   r   r1   msgs     r    r   zIBStore.watcherK  sQ    CH66KKOOS%

"5tCIIK7HIJ r"   c                 V    	 | j                   j                         S # t        $ r Y yw xY w)NF)r   isConnectedr   r   s    r    	connectedzIBStore.connectedQ  s/    
	99((** 		s    	((c                    d}	 | j                   j                         r|r| j                          y	 | j                  ry| j
                  j                  }|dk\  r||z  }|dk  s|ro|s)t        j                  | j
                  j                         d}| j                   j                         r|r|r| j                          y|dkD  r|dz  }|dk  rl|rod| _        y# t        $ r d}Y w xY w)NFTr   rj   )r   r   
startdatasr   r   r   r\   timesleepr^   connect)r1   r   resubfirstconnectretriess        r    r\   zIBStore.reconnect]  s     	 yy$$&OO% '  &&""a<|#GkW

466>>* Lyy  " EOO%{1 kW ";  	   L	 s   ,C C+*C+c                     t               }| j                  D ]C  }t        j                  |j                        }|j                          |j                  |       E |D ]  }|j                           y N)target)r   r   rz   Threadreqdatar   r   join)r1   r   r   rq   s       r    r   zIBStore.startdatas  s^    VJJ 	D  5AGGIIIaL	
  	AFFH	r"   c                 r   t        | j                  j                               }t               }| j                  D ]C  }t	        j
                  |j                        }|j                          |j                  |       E |D ]  }|j                           t        |      D ]  }|j                  d         y r   )r   r   r   r   rz   r   
canceldatar   r   r   reversedr   )r1   r   r   r   rq   qs         r    	stopdataszIBStore.stopdatas  s    $''.."#VJJ 	D  8AGGIIIaL	
  	AFFH	 " 	AEE$K	r"   c                     | j                   j                  d       t               }	 | j                   j                         }|	 |S |j	                  |       1)z(Return the pending "store" notificationsN)r   r   r   getr   )r1   r   notifs      r    get_notificationszIBStore.get_notifications  sP     	KKOO%E}  MM% 	 r"   c                    | j                   j                  sL| j                  j                  |t	        |j                               t        |j                               f       |j                  y |j                  dv r-	 | j                  |j                     }| j                  |d       y |j                  dv rH	 | j                  |j                     }|j                  |j                          | j                  |       y |j                  dk(  r7	 | j                  |j                     }|j                  |j                          y |j                  dk(  r2d| _        | j                  j                          | j!                          y |j                  dk(  r+| j                  j                          | j!                          y |j                  dk(  ry |j                  dk(  r+| j                  j                          | j!                          y |j                  d	k(  r.| j"                  D ]  }|j                  |j                            y |j                  d
k(  r.| j"                  D ]  }|j                  |j                            y |j                  dk(  r.| j"                  D ]  }|j                  |j                            y |j                  dk  rn|j                  | j$                  k  r)| j&                  | j&                  j)                  |       y y | j                  |j                     }| j                  |d       y y # t        $ r Y y w xY w# t        $ r Y y w xY w# t        $ r Y y w xY w)N)         i@  iA  iB  T)ib  i  i'  iF  i  i  i  iL  iM  iN  i  )r   rZ   r   r   r   r   r   r   	errorCoder   idcancelQueueKeyErrorr   r   r   r   r   r   r   push_ordererror)r1   r   r   s      r    errorzIBStore.error  s    vvKKOOS%

"5tCIIK7HIJ == ]]<<*GGCFFO   D)]]j($GGCFFO s}}n%  #]]e#&GGCFFO s}}n%]]c!!%DII  "NN]]c!II  "NN]]c!]]d" II  "NN]]d" WW &s}}n%& ]]d"WW &s}}n%& ]]d"WW &s}}n%& ]]S  vv&;;*KK//4 + GGCFFO  D) !}      s6   ?M :M M 	MM	MM	M+*M+c                 X    | j                   j                          | j                          y rD   )r   r   r   r   s     r    connectionClosedzIBStore.connectionClosed  s     			r"   c                     |j                   j                  d      | _        | j                  j	                          | j                          y )N,)accountsListr-   r   r   r   reqCurrentTimer   s     r    managedAccountszIBStore.managedAccounts#  s=     !$ 0 0 6 6s ;$$((* 	r"   c                 8    | j                   j                          y rD   )r   r   r   s    r    r   zIBStore.reqCurrentTime,  s    		  "r"   c                    | j                   j                  sy t        j                  t	        |j
                              }| j                  5  |t        j                         z
  | _        d d d        t        j                  | j                   j                  | j                        j                          y # 1 sw Y   LxY wrD   )r   r_   r	   fromtimestampr=   r   r   nowr3   rz   Timerr`   r   r   )r1   r   curtimes      r    currentTimezIBStore.currentTime/  s    vv  ((sxx9   	5#hlln4DM	5 	**D,?,?@FFH	5 	5s   B44B=c                 ^    | j                   5  | j                  cd d d        S # 1 sw Y   y xY wrD   )r   r3   r   s    r    r_   zIBStore.timeoffset9  s'       	!==	! 	! 	!s   #,c                 ,    t        | j                        S rD   )r0   r   r   s    r    nextTickerIdzIBStore.nextTickerId=  s    DNN##r"   c                 L    t        j                  |j                        | _        y rD   )r   r   orderIdr   r   s     r    nextValidIdzIBStore.nextValidIdA  s     !s{{3r"   c                 ,    t        | j                        S rD   )r0   r   r   s    r    nextOrderIdzIBStore.nextOrderIdF  s     DLL!!r"   c                 <   | j                   5  | j                  j                  |d      }| j                  j                  |d      }| j	                         }|| j
                  |<   || j                  |<   || j                  |<   ddd       ||fS # 1 sw Y   |fS xY w)z;Reuses queue for tickerId, returning the new tickerId and qN)r|   r   popr   r  r   )r1   tickerIdr   r   s       r    
reuseQueuezIBStore.reuseQueueK  s    \\ 		+Hd+A[[__Xt4F ((*H!DGGAJ !DGGH$*DKK!		+ {		+ {s   A6BBc                    t        j                         }|r|j                  d       |S | j                  5  | j	                         }|| j
                  |<   || j                  |<   d| j                  |<   ddd       ||fS # 1 sw Y   |fS xY w)z5Creates ticker/Queue for data delivery to a data feedNF)r   r   r   r|   r  r   r   r   )r1   r   r   r  s       r    r   zIBStore.getTickerQueueZ  s    KKMEE$KH\\ 	*((*H !DGGH!DGGAJ$)DKK!		* {	* {s   >B  Bc                     | j                   j                  |d      }| j                  j                  |d       | j                  j                  |d       |r|j	                  d       yy)z!Cancels a Queue for data deliveryN)r   r  r   r   r   )r1   r   sendnoner  s       r    r   zIBStore.cancelQueuei  sO     77;;q$'Hd#$'EE$K r"   c                     || j                   v S )z)Returns (bool)  if a queue is still valid)r   r1   r   s     r    
validQueuezIBStore.validQueuet  s    DGG|r"   c                     t               }| j                  |      }	 |j                         }|n|j                  |       %|r|r/t	        |      |kD  r!d}| j
                  j                  ||i f       y |S )Nz2Ambiguous contract: none/multiple answers received)r   reqContractDetailsr   r   lenr   r   )r1   contractmaxcountcdsr   r   errs          r    getContractDetailszIBStore.getContractDetailsx  st    f##H-%%'C{JJsO	  xCHx$7FCKKOOS#rN+
r"   c                 d    | j                         \  }}| j                  j                  ||       |S rD   )r   r   r  )r1   r  r  r   s       r    r  zIBStore.reqContractDetails  s-    ))+!		$$Xx8r"   c                 V    | j                  | j                  |j                     d       y)zSignal end of contractdetailsTN)r   r   reqIdr   s     r    contractDetailsEndzIBStore.contractDetailsEnd  s!     	+T2r"   c                 T    | j                   |j                     j                  |       y)z'Receive answer and pass it to the queueN)r   r   r   r   s     r    contractDetailszIBStore.contractDetails  s     			s#r"   c                 r   t               j                         }|j                  dd       |t        j                  k  r| j                  d      S |t        j                         }|| j                  ||      }|2d}| j                  j                  |d|f       | j                  d      S | j                  ||      }|2d}| j                  j                  |d|f       | j                  d      S | j                  ||||||||	      S | j                  ||      }|s| j                  d      S |
| j                         \  }
}n| j                  |
      \  }
}d}|D ]  }| j                  ||      }||k\  s|}|} n |&|d	   }t!        ||||||||	
	      | j"                  |
<   | j                  ||      }|t        j$                  k\  | j&                  |
<   |	| j(                  |
<   || j*                  |
<   |j,                  dv rd| j.                  |
<   |s6d}n3|j,                  dv r%| j0                  j2                  rd| j.                  |
<   |xs d}| j4                  j                  |
|t7        j9                  d      dz         t7        |      t7        |      t7        |      t;        |      d       |S )a%  
        Extension of the raw reqHistoricalData proxy, which takes two dates
        rather than a duration, barsize and date

        It uses the IB published valid duration/barsizes to make a mapping and
        spread a historical request over several historical requests if needed
        r1   NTr   zANo duration for historical data request for timeframe/compresisonr@   zJNo supported barsize for historical data request for timeframe/compresison)r  enddater   r   whatuseRTHtz
sessionend)	r  r%  	begindate	timeframecompressionr&  r'  r(  r)  CASHCFDrj   BID)IND   TRADES%Y%m%d %H:%M:%S GMTrk   )localsr   r  r   Secondsr   r	   r   getmaxdurationr   r   tfcomp_to_sizereqHistoricalDatagetdurationsr  dt_plus_durationr   r   Daysr   r   r   	m_secTyper   r   ra   r   r   strftimer>   )r1   r  r%  r+  r,  r-  r&  r'  r(  r)  r  rN   r   r  r   	durationsr   durintdates                      r    reqHistoricalDataExzIBStore.reqHistoricalDataEx  s    

64 y(((&&T&22?llnG**9kBH/b& 12***66)))[AG/b& 12***66))8W3;W/3Fr5? * A A %%i=	&&T&22 --/KHa//(3KHa  	C++Is;G'!!	  }H (,!7g#&RJ(HDNN8$
 %%i=!*inn!<X",h "H0$%DKK!7*tvv~~$%DKK!x		##'""#45>?(O'N$KK	 r"   c	                 *   | j                         \  }	}
|j                  dv r)d| j                  |	<   |sd}n|dk(  rd| j                  |	<   n|xs d}| j                  |j	                         d      d   }|t
        j                  k\  | j                  |	<   || j                  |	<   || j                  |	<   | j                  j                  |	|t        |j                  d	      d
z         t        |      t        |      t        |      t        |      d       |
S )zProxy to reqHistorical Datar.  Tr1  ASKrk   r4  rj   r   r5  r6  )r   r?  r   rn   r-   r   r>  r   r   r   r   r;  r   r@  r>   )r1   r  r%  r   r   r&  r'  r(  r)  r  r   tframes               r    r;  zIBStore.reqHistoricalData  s   
 ))+!0$(DKK!()H%#8D W]]_Q/03!'9>>!9X",h "H		##'""#45>?(O'N$KK	 r"   c                     | j                   5  | j                  j                  | j                  |          | j	                  |d       ddd       y# 1 sw Y   yxY w)ztCancels an existing HistoricalData request

        Params:
          - q: the Queue returned by reqMktData
        TN)r|   r   cancelHistoricalDatar   r   r  s     r    rI  zIBStore.cancelHistoricalData  sJ     \\ 	&II**4771:6Q%	& 	& 	&s   ;AAc           	          | j                         \  }}| j                  j                  |||t        d      t	        |             |S )ab  Creates a request for (5 seconds) Real Time Bars

        Params:
          - contract: a ib.ext.Contract.Contract intance
          - useRTH: (default: False) passed to TWS
          - duration: (default: 5) passed to TWS, no other value works in 2016)

        Returns:
          - a Queue the client can wait on to receive a RTVolume instance
        r4  )r   r   reqRealTimeBarsr   r>   )r1   r  r'  r   r  r   s         r    rK  zIBStore.reqRealTimeBars%  sH     ))+! 			!!(OK	 r"   c                     | j                   5  | j                  j                  |d      }|| j                  j	                  |       | j                  |d       ddd       y# 1 sw Y   yxY wzuCancels an existing MarketData subscription

        Params:
          - q: the Queue returned by reqMktData
        NT)r|   r   r   r   cancelRealTimeBarsr   r1   r   r  s      r    rN  zIBStore.cancelRealTimeBars=  s\     \\ 	&ww{{1d+H#		,,X6Q%	& 	& 	&   AA""A+c                     | j                         \  }}d}|j                  dv r%d| j                  |<   d}|dk(  rd| j                  |<   | j                  j	                  ||t        |      d       |S )zCreates a MarketData subscription

        Params:
          - contract: a ib.ext.Contract.Contract intance

        Returns:
          - a Queue the client can wait on to receive a RTVolume instance
        233r.  Tr8   rF  rk   F)r   r?  r   r   
reqMktDatar   )r1   r  r&  r  r   tickss         r    rS  zIBStore.reqMktDataJ  st     ))+!0$(DKK!Eu}()H% 			XxuuEr"   c                     | j                   5  | j                  j                  |d      }|| j                  j	                  |       | j                  |d       ddd       y# 1 sw Y   yxY wrM  )r|   r   r   r   cancelMktDatar   rO  s      r    rV  zIBStore.cancelMktDatab  s\     \\ 	&ww{{1d+H#		''1Q%	& 	& 	&rP  c                     |j                   dk(  r?	 t        |j                        }| j                  |j                     j                  |       y y # t        $ r Y y w xY w)N0   )tickTyper$   valuer   r  r   
ValueError)r1   r   r2   s      r    
tickStringzIBStore.tickStringo  sY     <<21 + %))%0   s   A 	AAc                 @   |j                   }| j                  |   }|rc|j                  |k(  rS	 |j                  dk(  ry	 	 t        |j                  | j                        }| j                  |   j                  |       yyy# t        $ r Y Nw xY w# t        $ r Y yw xY w)aK  Cash Markets have no notion of "last_price"/"last_size" and the
        tracking of the price is done (industry de-facto standard at least with
        the IB API) following the BID price

        A RTVolume which will only contain a price is put into the client's
        queue to have a consistent cross-market interface
        g      N)r%   r3   )
r  r   fieldr%   r   r$   r3   r   r   r[  )r1   r   r  	fieldcoder2   s        r    	tickPricezIBStore.tickPrice|  s     <<KK)	yyI%yyD(  )1$399t}}ME
 GGH%))%0 &  &  " s#   B  !B 	BB	BBc                     t        j                  t        |j                              |_        | j                  |j
                     j                  |       y)zReceives x seconds Real Time Bars (at the time of writing only 5
        seconds are supported)

        Not valid for cash markets
        N)r	   r   r=   r   r   r   r   r   s     r    realtimeBarzIBStore.realtimeBar  s9     ,,U388_=		s#r"   c                    |j                   }| j                  |   }|j                  j                  d      r| j                  j                  |d       | j                  j                  |d       | j                  j                  |d       | j                  j                  |d      }| | j                  dd|i| yd|_        | j                  |       n|j                  }| j                  |   r| j                  |   }t        j                  |d      }t        j                  ||      }| j                  |   }	|	r7|	j                  |      }
|
j                  t               j#                  d      }n|}|t        j$                         k  r|}||_        n#t        j&                  t)        |            |_        |j+                  |       y)z0Receives the events of a historical data requestz	finished-Nr  z%Y%m%d)tzinfor@   )r   r   r   
startswithr   r  r   r   r   rD  r   r	   strptimecombinelocalize
astimezoner   r   r   r   r   r   )r1   r   r  r   kargsdtstrr)  dtdteosr(  dteostzdteosutcs               r    historicalDatazIBStore.historicalData  sz    99GGH88{+LLXt,MMh-KKOOHd+NN&&x6E (((D(DeDCHQHHE||H%!]]84
&&uh7 ((Z8[[* kk%0G&11#6>>d>KH  %Hx00!B#44T%[A	c
r"   ))z60 S)1 secs5 secs10 secs15 secs30 secs1 min)z120 S)rq  rr  rs  rt  ru  rv  2 mins)z180 S)rq  rr  rs  rt  ru  rv  rw  3 mins)z300 S)	rq  rr  rs  rt  ru  rv  rw  rx  5 mins)z600 S)
rq  rr  rs  rt  ru  rv  rw  rx  ry  10 mins)z900 S)rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  15 mins)z1200 S)rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  20 mins)z1800 S)rq  rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  30 mins)z3600 S)rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  1 hour)z7200 S)rr  rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  2 hours)z10800 S)rs  rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  3 hours)z14400 S)rt  ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r  4 hours)z28800 S)ru  rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r  r  8 hours)z1 D)rv  rw  rx  ry  rz  r{  r|  r}  r~  r  r  r  r  1 day)z2 D)rw  rx  ry  rz  r{  r|  r}  r~  r  r  r  r  r  )1 W)rx  ry  rz  r{  r|  r}  r~  r  r  r  r  r  r  )z2 W)
r{  r|  r}  r~  r  r  r  r  r  r  )1 M)	r}  r~  r  r  r  r  r  r  r  )2 Mr  r  r  )z3 Mr  )z4 Mr  )z5 Mr  )z6 Mr  )z7 Mr  )z8 Mr  )z9 Mr  )z10 Mr  )z11 Mr  )1 Yr  rj   <   )secsminminshourhoursdayWM)SDr  r  Yc                 H    ||f}|| j                   vrg S | j                   |   S rD   )r   r1   r,  r-  ry   s       r    r<  zIBStore.getdurationsm  s,    +&dkk!I{{3r"   c                 Z    ||f}	 | j                   |   d   S # t        t        f$ r Y y w xY w)Nr*  )r   r   
IndexErrorr  s       r    r9  zIBStore.getmaxdurationt  s?    +&	;;s#B''*% 		s    **c                    |t         j                  k(  rdj                  |      S |t         j                  k(  rdj                  |      S |t         j                  k(  r*|dz  sdj                  |dz        S dj                  |      S |t         j
                  k(  r>|dz  s|dz  }dj                  |      d|dkD  z  z   S d	j                  |      d|dkD  z  z   S |t         j                  k(  rd
j                  |      S y )N{} M{} W   z{} dayr  z{} hoursrj   z{} minz{} secs)r   MonthsformatWeeksr>  Minutesr8  )r1   r,  r-  r  s       r    r:  zIBStore.tfcomp_to_size}  s    	(((==--	'==--	&?}}[A%566??;//	)))##r)!((/C5194EFFOOK0SK!O5LMM	)))##K00 r"   c                    |j                         \  }}t        |      }|dk(  r|t        |      z   S |dk(  r|t        |      z   S |dk(  r|t        |dz        z   S |dk(  rD|j                  dz
  |z   }t	        |d	      \  }}|j                  |j                  |z   |dz   
      S |dk(  r|j                  |j                  |z         S |S )Nr  )secondsr  )daysr  r  r  rj      )yearmonthr  )r  )r-   r>   r
   r  r   r   r  )r1   rl  r   r&   dimr  yearss          r    r=  zIBStore.dt_plus_duration  s    NN$	c4y#:	$///#:	t,,,#:	tax000#:HHqL4'E!%,LE5::277U?%!):DD#:::277T>:22	r"   c                 
   | j                  ||      }|d   dk(  rFt        |j                         d         }t        d|      }t	        d|      }dj                  |      }n|d   dk(  rd}n|}| j                  t           }||fS )	z+Calculate a duration in between 2 datetimesr*  r  r   rk   rj   r  r  r  )histdurationr>   r-   r  maxr  r   checkduration)	r1   dtbegindtendr   mm1m2checkdursizess	            r    calcdurationszIBStore.calcdurations  s    $$We4B<3HNN$Q'(AQBQB}}R(Hb\S HH.r"   c                 :    | j                  ||      \  }}||d   fS )z@Calculate a duration in between 2 datetimes. Returns single sizer   )_calcdurations)r1   r  r  r   r  s        r    calcdurationzIBStore.calcduration  s'    --gu=%q!!r"   c                    ||z
  }|j                         }g d}t        j                  ||      }|t        |      k  rdj	                  ||         S t        |j                  xs |j                        }|j                  |z   }|j                  dk  rdj	                  |      S t        |j                  d      \  }	}
|	t        |
xs |      z  }	|	dk  rdj	                  |	      S |j                  |j                  |j                  }}}|j                  |j                  |j                  }}}|j                  |j                  |j                  |j                   f\  }}}}|j                  |j                  |j                  |j                   f\  }}}}|dz  |z   |dz  |z   z
  |||||f|||||fkD  z   }|dk  ry	|d
k  ryy)N)r  x      i,  iX  i  i  i  i  i   i0*  i@8  ip  z{} Srk   z{} Dr  r  r  rj   r     r  r  )total_secondsbisectbisect_leftr  r  r?   r  microsecondsr  r   r  r  r  r  minutesecondr   )r1   dt1dt2tdtsecsr  idxsectdextrar  weeksrw   y2r  d2y1r  d1H2M2S2US2H1M1S1US1monthss                             r    r  zIBStore.histduration  s    3Y   " ##D%0CI==f..rzz4R__5 ww 77a<==&& "''1%qal7##A:=='' XXsyy#''BXXsyy#''B((CJJ

COOKBC((CJJ

COOKBC r'B,27R<0RS!RRS$99;Q;r\ r"   c	                     t               }	t        |      |	_        t        |      |	_        t        |      |	_        |rt        |      |	_        |dv rt        |      |	_        |dv r||	_        t        |      |	_        |rt        |      |	_	        |	S )z4returns a contract from the parameters without check)FUTOPTFOP)r  r  )
r   r   m_symbolr?  
m_exchange
m_currencym_expirym_strikem_rightm_multiplier)
r1   symbolsectypeexchcurrexpirystrikerightmultr  s
             r    makecontractzIBStore.makecontract  s     :!&M"7^#Dk"'+H++ %fHn$ &H$U|H$)$KH!r"   c                 :    | j                   j                  |       y)zProxy to cancelOrderN)r   cancelOrder)r1   r   s     r    r  zIBStore.cancelOrder  s    		g&r"   c                 >    | j                   j                  |||       y)zProxy to placeOrderN)r   
placeOrder)r1   r   r  orders       r    r  zIBStore.placeOrder  s    		Wh6r"   c                 :    | j                   j                  |       y)z&Receive the event ``openOrder`` eventsN)r   push_orderstater   s     r    	openOrderzIBStore.openOrder  s     	##C(r"   c                 N    | j                   j                  |j                         y)zReceive execDetailsN)r   push_execution	executionr   s     r    execDetailszIBStore.execDetails  s     	""3==1r"   c                 :    | j                   j                  |       y)z!Receive the event ``orderStatus``N)r   push_orderstatusr   s     r    orderStatuszIBStore.orderStatus   s     	$$S)r"   c                 N    | j                   j                  |j                         y)z"Receive the event commissionReportN)r   push_commissionreportcommissionReportr   s     r    r  zIBStore.commissionReport%  s     	))#*>*>?r"   c                 8    | j                   j                          y)zProxy to reqPositionsN)r   reqPositionsr   s    r    r  zIBStore.reqPositions*  s    		 r"   c                      y)zReceive event positionsNr@   r   s     r    positionzIBStore.position.  s     	r"   c                     |)| j                   j                          | j                  d   }| j                  j	                  |t        |             y)zProxy to reqAccountUpdates

        If ``account`` is ``None``, wait for the ``managedAccounts`` message to
        set the account codes
        Nr   )r   waitr   r   reqAccountUpdatesr   )r1   	subscribeaccounts      r    r  zIBStore.reqAccountUpdates3  sC     ?((--/++A.G		##IuW~>r"   c                 8    | j                   j                          y rD   )r   r   r   r   push_portupdater   s     r    accountDownloadEndzIBStore.accountDownloadEnd?  s    
 	##%r"   c                    | j                   5  | j                  j                         sDt        |j                  |j
                        }|| j                  |j                  j                  <   n| j                  |j                  j                     }|j                  |j                  |j
                        s d}| j                  j                  |di f       | j                  j                          d d d        y # 1 sw Y   y xY w)NzThe current calculated position and the position reported by the broker do not match. Operation can continue, but the trades calculated in the strategy may be wrongr@   )r~   r   is_setr   r   averageCostr   r  m_conIdfixr   r   r   r  )r1   r   r   r  s       r    updatePortfoliozIBStore.updatePortfolioK  s     ^^ 	.**113#CLL#//B7?s||334>>#,,*>*>?||CLL#//BEC
 KKOOS"bM2 ++-!	. 	. 	.s   C"C88Dc                     | j                   5  | j                  |j                     }|rt        |      cd d d        S |cd d d        S # 1 sw Y   y xY wrD   )r~   r   r  r   )r1   r  cloner   s       r    getpositionzIBStore.getpositiona  sM     ^^ 	~~h&6&67HH~	 	
 	 	 	s   &AAAc                    | j                   5  	 t        |j                        }|| j                  |j
                     |j                     |j                  <   |j                  dk(  r|| j                  |j
                  <   n7|j                  dk(  r(|j                  dk(  r|| j                  |j
                  <   d d d        y # t        $ r |j                  }Y w xY w# 1 sw Y   y xY w)NNetLiquidationTotalCashBalanceBASE)
r}   r=   rZ  r[  r   accountNamery   currencyr   r   )r1   r   rZ  s      r    updateAccountValuezIBStore.updateAccountValuek  s      	7"cii( EJDMM#//*3773CLLAww**27s/..3<<63I16coo.	7 	7  "		"	7 	7s.   CC BC CCCCC$c                    | j                         r| j                  j                          | j                  5  || j                         r| j                  j                          | j
                  s#| j                  j                         cddd       S t        | j
                        dkD  r#| j                  j                         cddd       S | j
                  d   }	 | j                  |   j                         cddd       S # t        $ r Y nw xY w| j                  j                         cddd       S # 1 sw Y   yxY w)a|  Returns all account value infos sent by TWS during regular updates
        Waits for at least 1 successful download

        If ``account`` is ``None`` then a dictionary with accounts as keys will
        be returned containing all accounts

        If account is specified or the system has only 1 account the dictionary
        corresponding to that account is returned
        Nrj   r   )
r   r   r  _updacclockr   r   r   r   r  r   r1   r  s     r    get_acc_valueszIBStore.get_acc_values}  s    >>##((* 	(>>#00557,,==--/	( 	( ../!3==--/	( 	( //2}}W-224!	( 	("   ==%%')	( 	( 	(s6   AD61D6D6D	DD6DD66D?c                 :   | j                         r| j                  j                          | j                  5  || j                         r| j                  j                          | j
                  st               cddd       S t        | j
                        dkD  r,t        | j                  j                               cddd       S | j
                  d   }	 | j                  |   cddd       S # t        $ r Y nw xY wt               cddd       S # 1 sw Y   yxY w)a~  Returns the net liquidation value sent by TWS during regular updates
        Waits for at least 1 successful download

        If ``account`` is ``None`` then a dictionary with accounts as keys will
        be returned containing all accounts

        If account is specified or the system has only 1 account the dictionary
        corresponding to that account is returned
        Nrj   r   )r   r   r  r}   r   r   r=   r  sumr   r   r   r  s     r    get_acc_valuezIBStore.get_acc_value  s     >>##((* 	>>#00557,, 7	 	 ../!3t~~4467	 	 //2~~g.!	 	"   7)	 	 	s6   AD:DDC//	C;8D:C;;DDc                 (   | j                         r| j                  j                          | j                  5  || j                         r| j                  j                          | j
                  st               cddd       S t        | j
                        dkD  r,t        | j                  j                               cddd       S | j
                  d   }	 | j                  |   cddd       S # t        $ r Y nw xY w	 ddd       y# 1 sw Y   yxY w)ay  Returns the total cash value sent by TWS during regular updates
        Waits for at least 1 successful download

        If ``account`` is ``None`` then a dictionary with accounts as keys will
        be returned containing all accounts

        If account is specified or the system has only 1 account the dictionary
        corresponding to that account is returned
        Nrj   r   )r   r   r  r}   r   r   r=   r  r  r   r   r   r  s     r    get_acc_cashzIBStore.get_acc_cash  s     >>##((* 	>>#00557,, 7	 	 ../!3t}}3356	 	 //2}}W-!	 	"  %	 	 	s6   AD:DDC//	C;8D:C;;DD)NN)FF)FrD   )NFr8   NN)NFr8   N)F   )r8   g        r8   rj   )TN)Vr9   r:   r;   r<   r   rg   rc   paramsclassmethodre   rh   r7   r   r   r   r   r   r\   r   r   r   rT   r   r   r   r   r  r_   r  r	  r  r  r   r   r  r  r  r!  r#  rD  r;  rI  rK  rN  rS  rV  r\  r`  rb  rp  r   r   r   r8  r  r>  r  r  rn   Yearsrv   r<  r9  r:  r=  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r!  rO   rP   s   @r    rV   rV   i   s}   <B IIGF , , . .c2J! &
K
1f	 a* a*F    # I I!$ 4 4"
	  3 3 $ $ HL%)_D FJ D&0&0& 
1 
1 1 1> $ $ * *b  } }JD ""A&!!1%""A&""B'##R("ooq!"	F ^^____G 4,""
6r <=&'7 ) ) 2 2 * * @ @!  
? 	) 	) . .* 7 7"#(J#J!r"   rV   rD   )(
__future__r   r   r   r   r   r   r	   r   r
   r   r   r   rz   r   ib.ext.Contractr   ib.optoptr   
backtraderr   r   backtrader.metabaser   backtrader.utils.py3r   r   r   r   r   backtrader.utilsr   r   r!   objectr$   rB   rT   rV   r@   r"   r    <module>r/     s~   ** *   . .      $  * * I I *D&v &>J 
n]F3 r"   