B
     9-ek                 @   s  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 d dlmZ d dlmZ d dlmZmZm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 d dl m!Z! d dl"m#Z# G dd de$Z%G dd de$Z&dd Z'dd Z(G dd de
j)eeZ*dS )    N)FileLock)IBCpp)read_hash_config)ReqType)from_security_to_contract)ReqAttrActiveRequestBatchReqHeartBeats)LostHeartBeat)	Converter)print_IBCpp_contractprint_IBCpp_order)EClient)EWrapper)comm)exitc               @   sD   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dS ) CollectionRealTimePriceRequestedc             C   s   i | _ i | _d S )N)_realTimePriceRequestById"_realTimePriceRequestByStrSecurity)self r   G:\My Drive\STUDY\EPAT\09 TBP - Trading & Back-testing Platforms\TBP04 - Backtesting & Live Trading\IB IBridgePy API\02 Python 3.7 IBridgePy_Win_Anaconda37_64\broker_client_factory\BrokerClient.py__init__   s    z)CollectionRealTimePriceRequested.__init__c             C   s   || j |< || j|< d S )N)r   r   )r   reqIdstr_securityr   r   r   addReqIdAndStrSecurity    s    
z7CollectionRealTimePriceRequested.addReqIdAndStrSecurityc             C   s   | j |= | j|= d S )N)r   r   )r   r   r   r   r   r   deleteReqIdAndStrSecurity$   s    z:CollectionRealTimePriceRequested.deleteReqIdAndStrSecurityc             C   s6   || j kr,td| j f  ttd|f   | j | S )Nz%self._realTimePriceRequestByIdself=%sz)::findByReqId: EXIT, there is no reqId=%s)r   printr   __name__)r   r   r   r   r   findByReqId(   s    
z,CollectionRealTimePriceRequested.findByReqIdc             C   s
   | j | S )N)r   )r   r   r   r   r   findByStrSecurity.   s    z2CollectionRealTimePriceRequested.findByStrSecurityc             C   s   | j S )zq
        Get all securities that have requested real time prices
        :return: a list of str_security
        )r   )r   r   r   r   getAllStrSecurity1   s    z2CollectionRealTimePriceRequested.getAllStrSecurityc             C   s
   || j kS )N)r   )r   r   r   r   r   checkIfRequestedByStrSecurity8   s    z>CollectionRealTimePriceRequested.checkIfRequestedByStrSecurityN)
r   
__module____qualname__r   r   r   r   r    r!   r"   r   r   r   r   r      s   r   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
UuidFNc             C   s"   d| _ || _tj|dd| _d S )Nr   	IBridgePyzlock.txt)uuidsyncospathjoinlockFilePath)r   r(   rootFolderPathr   r   r   r   =   s    zUuid.__init__c             C   s   | j s|| _nt| j|S d S )N)r(   r'   set_orderId_to_lockr,   )r   valuer   r   r   setUuidC   s    zUuid.setUuidc             C   s,   | j s| j}|  jd7  _|S t| jS d S )N   )r(   r'   orderId_plus_one_write_to_lockr,   )r   ansr   r   r   useOneI   s
    zUuid.useOne)FN)r   r#   r$   r   r0   r4   r   r   r   r   r%   <   s   
r%   c          	   C   s   t | }|  t| df}| }|rbt||d< |d |d |d| |	  n|t|d  |	  W dQ R X dS )zb

    :param value: orderId to set in lock
    :param lockFilePath:
    :return: orderId, int
    zr+r   
N)
r   acquireopen	readlinesstrseektruncatewriter+   release)r,   r/   flflinesr   r   r   r.   R   s    


r.   c          	   C   s~   t | }|  t| dR}| }t|d  }t|d |d< |d |d |	d
| W dQ R X |  |S )z9

    :param lockFilePath:
    :return: orderId, int
    zr+r   r1   r5   N)r   r6   r7   r8   intstripr9   r:   r;   r<   r+   r=   )r,   r>   r?   r@   r3   r   r   r   r2   k   s    

r2   c               @   sf  e Zd ZdZdZdd ZdYddZdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zd:d; Z d<d= Z!d>d? Z"d@dA Z#dBdC Z$dDdE Z%dFdG Z&dHdI Z'dJdK Z(dLdM Z)dNdO Z*dPdQ Z+dRdS Z,dTdU Z-dVdW Z.dXS )ZBrokerClientBasea  
    !!!! Do not implement __init__, otherwise it will supersede IBCpp.__init__ and cause errors

    BrokerClientBase lists all of interface functions for outside.
        use_next_id --- used for placing combination orders TODO: can be removed by sharing nextId with brokerService
    singleTrader and dataFromServer are updated by BrokerClient and they are shared with BrokerService.
    z19.1.3c             C   s"   d| j t| | j| j| j| jf S )Nz:{name=%s id=%s accountCode=%s host=%s port=%s clientId=%s})nameid_accountCodehostportclientId)r   r   r   r   __str__   s    zBrokerClientBase.__str__Fc             C   s  t | |  || _|| _|| _|| _|| _t|	|d| _t	 | _
tj|dd}| t|}|dkrnt| t|tr| | j n
| d t|| jd| _ttj|dd| _| jtd  d | _d	| _d
| _d
| _d
| _i | _ d | _!|
| _"|j#j$| _%d | _&d | _'d | _(d S )N)r-   r&   z	hash.confOKAll)ZcreaterOfIBValuezsecurity_info.csvz::_setupFT))r   r   _logrF   _singleTrader_dataFromServer_timeGeneratorr%   _nextIdr   _realTimePriceRequestedListr)   r*   r+   setHashConfigr   r   
isinstancer9   setAuthedAcctCoder   _idConverterpdread_csv_security_infodebugr   _dataProvider_asDataProviderClient_connectionGatewayToServer_connectionMarketDataFarm_connectionHistDataFarm_allRequests_activeRequests_autoReconnectPremiumprojectConfigerrorsIgnoredByUser_errorsIgnoredByUserrG   rH   rI   )r   
userConfiglogaccountCoder-   singleTraderdataFromServertimeGeneratorbrokerClientNameZsyncUuidautoReconnectPremiumr*   respr   r   r   _setup   s>    



zBrokerClientBase._setupc          	   C   s   yy&| j jddd}| jd|  W n* tjk
rR   | jd |   Y n.X t	|}| jd| | j
| |   W n ttfk
r   t  Y nX d S )NTg?)blocktimeoutzprocess_messages:: text=zqueue.get: emptyz	fields %s)	msg_queuegetrM   notsetqueueEmptyrZ   Z
msgLoopTmor   Zread_fieldsdecoderZ	interpretZ
msgLoopRecKeyboardInterrupt
SystemExitr   )r   textfieldsr   r   r   process_messages   s    
z!BrokerClientBase.process_messagesc             C   s   | j S )N)r[   )r   r   r   r   getDataProvider   s    z BrokerClientBase.getDataProviderc             C   s
   d| _ d S )NT)r\   )r   r   r   r   setAsDataProviderClient   s    z(BrokerClientBase.setAsDataProviderClientc             C   s,   |   }| |}tj|dtj  jS )zO

        :return: int, number of days of IBridgePy passcode to expiry
        z%Y%m%d)getAuthedVersionZ	getExpirydtdatetimestrptimenowdays)r   ZauthedLevelexpiryr   r   r   get_authed_expiry   s    
z"BrokerClientBase.get_authed_expiryc             C   s   t | jd S )N)NotImplementedErrorrD   )r   r   r   r   "get_TD_access_token_expiry_in_days   s    z3BrokerClientBase.get_TD_access_token_expiry_in_daysc             C   s   t | jd S )N)r   rD   )r   r   r   r   get_new_TD_refresh_token   s    z)BrokerClientBase.get_new_TD_refresh_tokenc             C   s   |  t  d S )N)request_datar	   )r   r   r   r   get_heart_beats  s    z BrokerClientBase.get_heart_beatsc             C   s   | j t d |   d S )Nz::processMessagesWrapper)rM   rt   r   r|   )r   timeNowr   r   r   processMessagesWrapper  s    z'BrokerClientBase.processMessagesWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   isConnectedWrapper
  s    z#BrokerClientBase.isConnectedWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   connectWrapper  s    zBrokerClientBase.connectWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   disconnectWrapper  s    z"BrokerClientBase.disconnectWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqPositionsWrapper  s    z$BrokerClientBase.reqPositionsWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqCurrentTimeWrapper  s    z&BrokerClientBase.reqCurrentTimeWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqAllOpenOrdersWrapper  s    z(BrokerClientBase.reqAllOpenOrdersWrapperc             C   s   t | jd S )N)r   rD   )r   ibpyOrderIdr   r   r   reqOneOrderWrapper  s    z#BrokerClientBase.reqOneOrderWrapperc             C   s   t | jd S )N)r   rD   )r   	subscriberh   r   r   r   reqAccountUpdatesWrapper  s    z)BrokerClientBase.reqAccountUpdatesWrapperc             C   s   t | jd S )N)r   rD   )r   r   grouptagr   r   r   reqAccountSummaryWrapper"  s    z)BrokerClientBase.reqAccountSummaryWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqIdsWrapper%  s    zBrokerClientBase.reqIdsWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqHeartBeatsWrapper(  s    z%BrokerClientBase.reqHeartBeatsWrapperc	       	      C   s   t | jd S )N)r   rD   )	r   r   contractendTimegoBackbarSize
whatToShowuseRTH
formatDater   r   r   reqHistoricalDataWrapper+  s    z)BrokerClientBase.reqHistoricalDataWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   genericTickListsnapshotr   r   r   reqMktDataWrapper.  s    z"BrokerClientBase.reqMktDataWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   r   cancelMktDataWrapper1  s    z%BrokerClientBase.cancelMktDataWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   r   r   r   r   r   reqRealTimeBarsWrapper4  s    z'BrokerClientBase.reqRealTimeBarsWrapperc             C   s   t | jd S )N)r   rD   )r   r   orderibpyRequestr   r   r   placeOrderWrapper7  s    z"BrokerClientBase.placeOrderWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   r   r   r   modifyOrderWrapper:  s    z#BrokerClientBase.modifyOrderWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   r   r   reqContractDetailsWrapper=  s    z*BrokerClientBase.reqContractDetailsWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   optionPrice
underPricer   r   r   !calculateImpliedVolatilityWrapper@  s    z2BrokerClientBase.calculateImpliedVolatilityWrapperc             C   s   t | jd S )N)r   rD   )r   r   subscriptionr   r   r   reqScannerSubscriptionWrapperC  s    z.BrokerClientBase.reqScannerSubscriptionWrapperc             C   s   t | jd S )N)r   rD   )r   tickerIdr   r   r    cancelScannerSubscriptionWrapperF  s    z1BrokerClientBase.cancelScannerSubscriptionWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   r   cancelOrderWrapperI  s    z#BrokerClientBase.cancelOrderWrapperc             C   s   t | jd S )N)r   rD   )r   r   r   r   reqScannerParametersWrapperL  s    z,BrokerClientBase.reqScannerParametersWrapperc             C   s   | j | jS )N)r`   returnedResult)r   r   r   r   r   get_submit_requests_resultO  s    z+BrokerClientBase.get_submit_requests_resultc             C   s
   | j  S )N)rQ   r4   )r   r   r   r   use_next_idR  s    zBrokerClientBase.use_next_idc             C   s&   | j t d|  | j| S )Nz)::is_real_time_price_requested: security=)rM   rt   r   rR   r"   
full_print)r   securityr   r   r   is_real_time_price_requestedU  s    z-BrokerClientBase.is_real_time_price_requestedc             C   s&   | j t d|  | j| S )Nz0::is_5_second_real_time_bar_requested: security=)rM   rt   r   rR   r"   r   )r   r   r   r   r   #is_5_second_real_time_bar_requestedY  s    z4BrokerClientBase.is_5_second_real_time_bar_requestedc             G   sb  | j td  t|| j| _| | j x
| j s6| j  | j	 }t
|dkr$| j td  x|D ]}| j|}| j t| |jtjkr|jtjjkr| j d n,| js| j d n| j d | j d |jtjkrrt qrW |   t| j dtjtj d	|  | j!"  q.W | j #td
  | j #td  | j$ S )a2  
        !!! return a list of reqId, reqId != orderId
        TODO: do not repeat 20190705
        input:
        request_data(
                     ReqPositions(),
                     ReqAccountUpdates(True, 'test_me'),
                     ReqAccountSummary(),
                     ReqIds(),
                     ReqHistoricalData(self.sybmol('SPY'),
                                               '1 day', '10 D', dt.datetime.now()),
                     ReqMktData(self.sybmol('SPY')),
                     ReqRealTimeBars(self.symbol('SPY')),
                     ReqContractDetails(self.symbol('SPY')),
                     CalculateImpliedVolatility(self.symbol('SPY'), 99.9, 11.1),
                     ReqAllOpenOrders(),
                     CancelMktData(1),
                     ReqCurrentTime())
        z::request_datar1   z8::request_data: EXIT, the following requestRecord faileda   Hint 1: IBridgePy waits for broker responses for 30 seconds default and errors out if completed responses have not been recorded. Consider to increase waitForFeedbackInSeconds. Refer to https://ibridgepy.com/ibridgepy-documentation/#request_historical_dataz-Hint: Connection to Hist Data Farm is broken.zHint 1: The most common reason is that broker historical data service is not available at this moment, especially when the US market is closed. Try the request later.zHint 2: The less common reason is that the broker server does not respond if the request violates broker rules about bar size. Refer to http://interactivebrokers.github.io/tws-api/historical_limitations.html#non-available_hdz@ server did not respond to the request at all.
The current time=z 
Hint 1: Restart TWS or IB Gateway. 
Hint 2: Please close ALL IBridgePy instances if any and restart. 
Hint 3: Maybe the market is closed? Is the brokers server on maintenance? Consider trying it later.z*::request_data: All responses are receivedz::request_data: COMPLETED)%rM   rt   r   r   rQ   ra   _send_req_to_servercheck_all_completed.label_uncompleted_to_completed_if_not_followupfind_failed_requestslenerrorget_by_reqId_otherwise_exitr9   reqTyper   REQ_HIST_DATAstatusr   StatusSTARTEDr_   REQ_HEART_BEATSr
   e_disconnectRuntimeErrorrD   r   r   r   pytzUTCr   rP   get_current_timerZ   get_request_ids)r   argsZfailedReqIdsr   requestr   r   r   r   ]  s4    



 zBrokerClientBase.request_datac             C   sT  | j td| f   x6| D ](}||}|| j|< tjj|_	|j
}|j}| j d|f  |dkrv|   q"|dkr|  }|rtjj|_	n|  }|rtjj|_	q"|dkr|   q"|dkr|   q"|dkr|d }| | q"|d	kr|d
 }|d }	| |	| q"|dkr@|d }
|d }| ||
| q"|dkrT|   q"|tjkrj|   q"|dkr|d }|d }|d }|d }|d }|d }d}| |t||||||| q"|dkr|d }|d }|d }| j||  | |t||| q"|dkrP|d }| j| }|  | | j!||  q"|dkr|d }|d }|d }|d }| j||  | "|t|||| q"|dkr|d }|d }| #||| q"|d kr4|d! }|d }|d }|d }| j$%|| | j &d"|t'|t(|f  | )||| q"|d#krX|d }| *|t| q"|d$kr|d }t+|d% }t+|d& }| j||  | ,|t||| q"|d'kr|d( }| -|| q"|d)kr|d* }| .| q"|d+kr|d! }| j$/|}||d,< | 0| q"|d-kr.| 1  q"| j 2td.|f   | 3  q"W d/S )0zw
        pandas dataFrame: reqData
        All requests are defined in broker_client_factory::BrokerClientDefs
        z&::_send_req_to_server: brokerClient=%sz%sreqPositions
reqConnectreqCurrentTimereqAllOpenOrdersreqOneOrderorderIdreqAccountUpdatesrh   r   reqAccountSummaryr   r   reqIdsreqHistoricalDatar   r   r   r   r   r      
reqMktDatar   r   cancelMktDatareqRealTimeBars
placeOrderr   r   modifyOrderr   z/ModifyOrder ibpyOrderId=%s security=%s order=%sreqContractDetailscalculateImpliedVolatilityr   r   reqScannerSubscriptionr   cancelScannerSubscriptionr   cancelOrderint_orderIdreqScannerParametersz5::_send_req_to_server: EXIT, cannot handle reqType=%sN)4rM   rZ   r   r   r   r`   r   r   	SUBMITTEDr   r   paramr   r   	COMPLETEDr   r   r   r   r   r   r   r   r   r   r   r   rR   r   r   r   r    r   r   r   r   rV   ZverifyRelationshipinfor   r   r   r   floatr   r   r   fromBrokerToIBr   r   r   end)r   ZactiveRequestsr   aRequestr   r   r3   r   rh   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s    
























z$BrokerClientBase._send_req_to_serverc             C   s   t | jdS )z
        Stay in brokerClient so that it can be replaced by fetching from IB server.
        :param security:
        :return:
        N)r   rD   )r   r   r   r   r   add_exchange_to_securityC  s    z)BrokerClientBase.add_exchange_to_securityc             C   s   t | jdS )z
        Stay in brokerClient so that it can be replaced by fetching from IB server.
        :param security:
        :return:
        N)r   rD   )r   r   r   r   r   add_primaryExchange_to_securityO  s    z0BrokerClientBase.add_primaryExchange_to_securityc             C   s4   t j|j|j|jddgd}t | j|g| _dS )z
        Add security into security_info mini db so that user don't need to manully add them in security_info.csv
        :param security:
        :return:
        )symbolexchangeprimaryExchanger   )indexN)rW   	DataFramer   r   r   concatrY   )r   r   new_rowr   r   r   append_security_info[  s    z%BrokerClientBase.append_security_infoN)F)/r   r#   r$   __doc__versionNumberrJ   ro   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rC   ~   sZ   
O	8 /rC   )+r   r   r)   ru   pandasrW   r   ZBasicPyLib.fileLockr   r&   r   IBridgePy.IbridgepyToolsr   IBridgePy.constantsr   IBridgePy.quantopianr   &broker_client_factory.BrokerClientDefsr   r   r	   "broker_client_factory.CustomErrorsr
   Z)broker_client_factory.broker_client_utilsr   models.utilsr   r   Zibapi.clientr   Zibapi.wrapperr   Zibapir   sysr   objectr   r%   r.   r2   IBClientrC   r   r   r   r   <module>   s,   $