B
     9-e-4 ã               @   sÆ  d dl Zd dlZd dlZd dlm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mZmZmZmZmZ d dlmZmZmZmZ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#m$Z$m%Z% d dl&m'Z' d dl(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/ d dl0m1Z1 d dl2m3Z3 d dl4m5Z5 ej6j7ej6j8ej6j9ej6j9ej6j:ej6j;ej6j<ej6j=ej6j>ej6j?ej6j@ej6jAej6jBej6jCej6jDej6jEej6jFej6jGdœZHdd„ ZIdd„ ZJdd„ ZKG dd„ deLƒZMdS )é    N)Úexit)ÚDecimal)ÚroundToMinTick)ÚIBCpp)Úspecial_matchÚcreate_orderÚcheck_same_securityÚfrom_symbol_to_securityÚprint_decisionsÚsymbol)ÚOrderStatusÚFollowUpRequestÚ	OrderTypeÚOrderTifÚDataProviderName)Ú
QDataClass)ÚSecurity)ÚTimeBasedRulesÚ	calendarsÚfrom_contract_to_security)ÚMarketOrderÚ	StopOrderÚ
LimitOrder)ÚContext)ÚReqIdsÚReqAccountSummaryÚReqAccountUpdatesÚReqAllOpenOrdersÚReqCurrentTimeÚReqPositionsÚModifyOrder)ÚNotEnoughFund)ÚIbridgePyOrder)Ú%convert_hist_using_epoch_to_timestamp)Ú	ask_priceÚ	bid_priceÚ
last_priceÚpriceÚopenÚhighÚlowÚcloseÚvolumeÚask_sizeÚbid_sizeZ	last_sizeZask_option_computationZbid_option_computationZlast_option_computationZmodel_optionÚoption_call_open_interestÚoption_put_open_interestc             C   s    x|D ]}t | |ƒr|S qW d S )N)r   )Z	aSecurityZaListÚsecurity© r2   ú²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\IBridgePy\Trader.pyÚ_get_same_security_from_list3   s    

r4   c             C   s    x|D ]}t || ƒrdS qW dS )NTF)r   )Z
a_securityÚls_securityÚsecr2   r2   r3   Ú_is_in_security_list:   s    

r7   c             C   sj   t | | | ƒ}xT|| }tt|ƒt|ƒ ƒ}t|ƒt| ƒt|t|ƒƒƒ  |krZt|ƒS |d8 }qW d S )Né   )ÚintÚabsr   ÚfloatÚstr)Úportfolio_valueZtarget_percentÚcurrent_priceÚcurrent_shareZ	comm_funcZ	new_shareZnew_holding_amountZtrading_sharer2   r2   r3   Ú'calculate_target_share_under_commissionA   s    $r@   c            	   @   sd  e Zd ZdZdZg ZdZdZdZdd„ Z	dd„ Z
dd	„ Zed
d„ ƒZdd„ Zdd„ Zdd„ Zd¥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'd(„Zd§d)d*„Zd¨d+d,„Zd©d-d.„Zdªd3d4„Zd«d5d6„Z d¬d7d8„Z!d9d:„ Z"d;d<„ Z#d­d=d>„Z$d?d@„ Z%dAdB„ Z&dCdD„ Z'd®dEdF„Z(d¯dGdH„Z)d°dIdJ„Z*d±dKdL„Z+dMdN„ Z,d²dPdQ„Z-d³dRdS„Z.d0d0dTd2e/ 0dU¡ddfdVdW„Z1d´dXdY„Z2dZd[„ Z3dµd\d]„Z4d^d_„ Z5d¶d`da„Z6e7ƒ d0d&ddd2dfdbdc„Z8e7ƒ d0dd&fddde„Z9dfdg„ Z:e7ƒ d0dd&fdhdi„Z;e7ƒ d0dd&fdjdk„Z<e7ƒ d0dd&fdldm„Z=e7ƒ d0dd&fdndo„Z>e7ƒ d0d&fdpdq„Z?e7ƒ drd0d&fdsdt„Z@e7ƒ drd0d&fdudv„ZAe7ƒ drd&dd0fdwdx„ZBdydz„ ZCd·d{d|„ZDd}d~„ ZEd¸dd€„ZFd¹dd‚„ZGdƒd„„ ZHdºd…d†„ZId»d‡dˆ„ZJd¼d‰dŠ„ZKd½d‹dŒ„ZLddŽ„ ZMddeNjOfdd„ZPeQd‘d’„ ƒZRd“d”„ ZSd¾d•d–„ZTd¿d—d˜„ZUdÀd™dš„ZVd›dœ„ ZWddž„ ZXdŸd „ ZYdÁd¡d¢„ZZd£d¤„ Z[dS )ÂÚTraderTFNc             C   sˆ   d | _ d | _d | _d | _d | _d | _d | _d | _d | _d | _	d | _
d | _d | _d | _d | _d | _d | _d | _t| _d | _d | _d | _d S )N)Ú_userConfigÚ	_fileNameÚ	_logLevelÚ_accountCodeÚ_sysTimeZoneÚ_showTimeZoneÚ%_runScheduledFunctionBeforeHandleDataÚ_multiAccSummaryTagÚinitialize_quantopianÚhandle_data_quantopianÚbefore_trading_start_quantopianÚ_userLogÚ_logÚ_marketCalendarÚ_emailClientÚ_brokerServiceÚ_dataProviderServiceÚ_dataProviderFactoryÚTICK_TYPE_MAPPERÚtick_type_mapperÚcontextÚqDataÚ_simulate_commission)Úselfr2   r2   r3   Ú__init___   s,    zTrader.__init__c             C   s   d| j | jt| ƒf S )Nz/{brokerService=%s dataProviderService=%s id=%s})rQ   rR   Úid)rY   r2   r2   r3   Ú__str__ƒ   s    zTrader.__str__c             C   s   || _ |jj| _|jj| _|jj| _|jj| _	|j
| _|j| _|j| _|j| _|j| _|j| _|j| _|jj| _|j| _|j| _|j| _|jj| _| j jj | _!t"| jt#ƒsÂt"| jt$ƒsÂt"| jt%ƒrÖd| _&t$| jƒ| _'nd| _&| jh| _'t(| | j'ƒ| _)t*| ƒ| _+| jdkr| j ,d¡ t-ƒ  d S )NTFÚ z7EXIT, do not forget to change accountCode in userConfig).rB   ÚprojectConfigÚfileNamerC   ÚsysTimeZonerF   ÚshowTimeZonerG   ÚmultiAccountSummaryTagrI   ÚlogrN   ÚuserLogrM   ÚemailClientrP   ÚmarketCalendarrO   ÚbrokerServicerQ   ÚdataProviderServicerR   ÚdataProviderFactoryrS   ÚaccountCoderE   rJ   rK   rL   Ú$runScheduledFunctionBeforeHandleDatarH   ÚbacktesterConfigÚsimulateCommissionrX   Ú
isinstanceÚlistÚsetÚtupleÚmultiAccountFlagÚaccountCodeSetr   rV   r   rW   Úerrorr   )rY   Ú
userConfigr2   r2   r3   Úupdate_from_userConfig†   s8    





$

zTrader.update_from_userConfigc             C   s   | j jS )N)rQ   ÚversionNumber)rY   r2   r2   r3   rw   ¯   s    zTrader.versionNumberc             C   s   | j j ¡  d S )N)rB   ÚbrokerClientFactoryÚdisconnect_all_client)rY   r2   r2   r3   Úterminate_all_clients³   s    zTrader.terminate_all_clientsc             C   s   | j S )N)rQ   )rY   r2   r2   r3   ÚgetBrokerService¶   s    zTrader.getBrokerServicec             C   s   | j S )N)rN   )rY   r2   r2   r3   ÚgetLog¹   s    zTrader.getLogc             C   s   | j  td|f  ¡ | jS )zÑ
        The function is used in Repeater in MarketManagerBase.py to know if repeat should stop
        dummy input = because it can be program to stop based on an input datetime
        :return: bool
        z::getWantToEnd: dummyTimeNow=%s)rN   ÚnotsetÚ__name__Ú	wantToEnd)rY   ZdummyTimeNowr2   r2   r3   ÚgetWantToEnd¼   s    zTrader.getWantToEndc             C   s   d| _ |  ¡  d S )NT)r   Ú
disconnect)rY   r2   r2   r3   ÚsetWantToEndÅ   s    zTrader.setWantToEndc             C   s˜   |dkr,| j s| jS | j td ¡ tƒ  nh| j sf|| jkr@|S | j td|t| jƒf  ¡ tƒ  n.|| jkrt|S | j td|| jf  ¡ tƒ  d S )NÚdefaultz7::adjust_accountCode: EXIT, Must specify an accountCodezH::adjust_accountCode: EXIT, wrong input accountCode=%s accountCodeSet=%sze::adjust_accountCode: EXIT, wrong user input, accountCode=%s does not exist in Multi account codes=%s)rr   rE   rN   rt   r~   r   rs   r<   )rY   rj   r2   r2   r3   Úadjust_accountCodeÉ   s$    

zTrader.adjust_accountCodec             C   s
   | j  ¡ S )zO

        :return: int, number of days of IBridgePy passcode to expiry
        )rQ   Úget_ibpy_expiry_in_days)rY   r2   r2   r3   r…   â   s    zTrader.get_ibpy_expiry_in_daysc             C   s
   | j  ¡ S )N)rQ   Ú"get_TD_access_token_expiry_in_days)rY   r2   r2   r3   r†   é   s    z)Trader.get_TD_access_token_expiry_in_daysc             C   s
   | j  ¡ S )N)rQ   Úget_new_TD_refresh_token)rY   r2   r2   r3   r‡   í   s    zTrader.get_new_TD_refresh_tokenc             C   s
   | j  ¡ S )N)rQ   Úconnect)rY   r2   r2   r3   rˆ   ð   s    zTrader.connectc             C   s    | j  t› d¡ | j ¡  d S )Nz::disconnect: )rN   Údebugr~   rQ   r   )rY   r2   r2   r3   r   ó   s    zTrader.disconnectc             C   s,   | j  ¡  | j¡}| j td|f  ¡ |S )Nz::get_next_time: timeNow=%s)rQ   Úget_next_timeÚ
astimezonerF   rN   r}   r~   )rY   ÚtimeNowr2   r2   r3   rŠ   ÷   s    zTrader.get_next_timec             C   s   | j  ¡  dS )z§
        Trigger heart beats request to IB server
        :param dummy: to be scheduled by BasicPyLib.repeater.Event, it mush have one input.
        :return:
        N)rQ   Úget_heart_beats)rY   Údummyr2   r2   r3   r   ý   s    zTrader.get_heart_beatsrƒ   c             C   s6   | j  td| ¡ f  ¡ |  |¡}|  ||¡}|jS )Nz::count_positions:security=%s)rN   r‰   r~   Ú
full_printr„   Úget_positionÚamount)rY   r1   rj   Úadj_accountCodeÚpositionRecordr2   r2   r3   Úcount_positions  s    
zTrader.count_positionsc       	      C   s€   | j  td ¡ |  |¡}|  |¡}g }t| ¡ ƒ}x&|D ]}| j|d|d}| |¡ q:W |r|x|D ]}|  	|t
j¡ qfW d S )Nz::close_all_positions:r   )rj   )rN   r‰   r~   r„   Úget_all_positionsro   ÚkeysÚorder_targetÚappendÚorder_status_monitorr   ÚFILLED)	rY   ÚorderStatusMonitorrj   r’   Ú	positionsÚorderIdListÚadj_securitiesr1   ÚibpyOrderIdr2   r2   r3   Úclose_all_positions  s    



zTrader.close_all_positionsc             C   sj   |   |¡}g }x6|  |¡D ](}t||ƒs| j|d|d}| |¡ qW |rfx|D ]}|  |tj¡ qPW d S )Nr   )rj   )r„   r•   r7   r—   r˜   r™   r   rš   )rY   r5   r›   rj   r’   r   r1   rŸ   r2   r2   r3   Úclose_all_positions_except   s    


z!Trader.close_all_positions_exceptc             C   s`   | j  td ¡ |  |¡}| j |¡}x4|D ],}|| jtjtj	tj
tjgkr,|  |¡ q,W d S )Nz::cancel_all_orders)rN   r‰   r~   r„   rQ   Úget_all_ordersÚstatusr   rš   Ú	CANCELLEDÚINACTIVEÚPENDINGCANCELÚcancel_order)rY   rj   r’   ÚordersrŸ   r2   r2   r3   Úcancel_all_orders,  s    

zTrader.cancel_all_ordersÚUSDr]   ç        é   c             C   s.   t ||||||||	|
|d
}| jj|||dS )N)
ÚsecTyper   ÚcurrencyÚexchangeÚprimaryExchangeÚexpiryÚstrikeÚrightÚ
multiplierÚlocalSymbol)ÚwaitForFeedbackInSeconds)r   rQ   Úget_contract_details)rY   r­   r   Úfieldr®   r¯   r°   r±   r²   r³   r´   rµ   r¶   r1   r2   r2   r3   r·   8  s    

zTrader.get_contract_detailsc             K   s   | j  ||¡S )N)rQ   Úget_scanner_results)rY   r¶   Úkwargsr2   r2   r3   r¹   ?  s    zTrader.get_scanner_resultsc             C   s<   | j  td| ¡ ||f  ¡ | j |¡ | jj|||dS )NzE::get_option_greeks: security=%s fields=%s waitForFeedbackInSecond=%s)r¶   )rN   r‰   r~   r   rQ   Ú(add_exchange_primaryExchange_to_securityÚget_option_info)rY   r1   Úfieldsr¶   r2   r2   r3   r¼   B  s    zTrader.get_option_infoc             C   s*   | j  tdt|ƒf  ¡ | j |¡ dS )zò
        this function is created to fit the new RepeaterEngine because any functions to be scheduled must have two input
        times. It is easier to input two times to repeated function(?)
        :param timeNow:
        :return:
        z::processMessages: timeNow=%sN)rN   r}   r~   r<   rQ   ÚprocessMessages)rY   rŒ   r2   r2   r3   r¾   G  s    zTrader.processMessagesc             C   sb   | j  td|f  ¡ | j ¡ }||kr,d S | j  td|f  ¡ | j  td|›  ¡ tƒ  d S )Nz-::_validate_input_accountCode: accountCode=%szE::_validate_input_accountCode: EXIT, accountCode=%s is not acceptablez9::_validate_input_accountCode: possible accountCodes are )rN   r‰   r~   rQ   Úget_active_accountCodesrt   r   )rY   rj   ÚaccountCodeCallBackListr2   r2   r3   Ú_validate_input_accountCodeQ  s    
z"Trader._validate_input_accountCodec             C   sJ   | j  ¡ }|dkr | | j¡}n| t |¡¡}| j td|f  ¡ |S )zö
        Get the current datetime of IB system similar to that defined in Quantopian
        :param timezone: str, representing timezone defined by pytz, for example, 'US/Pacific' and 'US/Eastern'
        :return: a zoned python DateTime
        rƒ   z::get_datetime: timeNow=%s)	rQ   Úget_datetimer‹   rG   ÚpytzÚtimezonerN   r}   r~   )rY   rÄ   rŒ   Úansr2   r2   r3   rÂ   [  s    
zTrader.get_datetimec             C   s  | j  td ¡ | j  d| jf ¡ | j  d| jf ¡ | j tƒ ¡ | j t	ƒ ¡ | j
rx| j t| jdtƒ tƒ ¡ n| j td| jƒtƒ tƒ ¡ | j  td ¡ |  | j¡ | j  d¡ | j
rèx8| jD ]}|  |¡ |  |¡ qÊW n|  | j¡ |  ¡  | j  d¡ d S )	Nz::initialize_FunctionzIBridgePy version %szfileName = %s)ÚtagTz;::initialize_Function::start to run customers init functionz-####    Starting to initialize trader    ####z+####    Initialize trader COMPLETED    ####)rN   r‰   r~   Úinforw   rC   rQ   Úsubmit_requestsr   r   rr   r   rI   r   r   r   rE   rJ   rV   rs   rÁ   Údisplay_all)rY   ÚacctCoder2   r2   r3   Úinitialize_Functioni  s0    



zTrader.initialize_Functionc             C   sR   | j  td|f  ¡ | jr*| jr*|  ¡  |  | j| j¡ | jrN| jsN|  ¡  dS )z=Must have one parameter to be scheduled in IBridgePy repeaterz::repeat_Function: dummyTime=%sN)	rN   r}   r~   ÚrunScheduledFunctionsTodayrH   Ú_check_schedulesrK   rV   rW   )rY   Ú	dummyTimer2   r2   r3   Úrepeat_Function‘  s    zTrader.repeat_Functionc             C   s.   | j  tdt|ƒf  ¡ |  | j| j¡ dS )z=Must have one parameter to be scheduled in IBridgePy repeaterz+::before_trade_start_Function: dummyTime=%sN)rN   r‰   r~   r<   rL   rV   rW   )rY   rÎ   r2   r2   r3   Úbefore_trade_start_FunctionŸ  s    z"Trader.before_trade_start_Functionc             C   sº   | j  td|f  ¡ |  |¡}|  |¡}t|ƒdkrD| j  d¡ nr| j  d|f ¡ | j  d¡ xR|D ]J}|| j}|| j}|| j	}| j  t
|ƒd t
|ƒ d t
|ƒ ¡ qhW d S )Nz#::display_positions: accountCode=%sr   z##    NO ANY POSITION    ##z##    POSITIONS %s   ##zSymbol Amount Cost_basisú )rN   r}   r~   r„   r•   ÚlenrÇ   Ústr_securityr‘   Ú
cost_basisr<   )rY   rj   r’   rœ   r1   ÚaÚbÚcr2   r2   r3   Údisplay_positions¤  s    





zTrader.display_positionsc             C   sŠ   | j  td|f  ¡ |  |¡}| j |¡}t|ƒdkrz| j  d|f ¡ x |D ]}| j  t|| ƒ¡ qPW | j  d¡ n| j  d¡ d S )Nz%::display_orderStatus: accountCode=%sr8   z##    Order Status %s   ##z##    END    ##z##    NO any order    ##)	rN   r}   r~   r„   rQ   r¢   rÒ   rÇ   r<   )rY   rj   r’   r¨   rŸ   r2   r2   r3   Údisplay_orderStatusµ  s    

zTrader.display_orderStatusc             C   sÄ   | j  td|f  ¡ |  |¡}| j  d|f ¡ | j |d¡}| j |d¡}| j |d¡}| j  d|f ¡ | j  d|f ¡ | j  d|f ¡ || | d	k rÀ| j  td
| jf  ¡ t	ƒ  dS )zM
        display account info such as position values in format ways
        z&::display_account_info: accountCode=%sz##    ACCOUNT Balance  %s  ##ÚTotalCashValueÚNetLiquidationÚGrossPositionValuezCASH=%szportfolio_value=%szpositions_value=%sg        z:::display_account_info: EXIT, Wrong input accountCode = %sN)
rN   r}   r~   r„   rÇ   rQ   Úget_account_infort   rE   r   )rY   rj   r’   rÕ   rÖ   r×   r2   r2   r3   Údisplay_account_infoÂ  s    

zTrader.display_account_infoc             C   sB   | j  td|f  ¡ |  |¡}|  |¡ |  |¡ |  |¡ d S )Nz::display_all: accountCode=%s)rN   r‰   r~   r„   rÞ   rØ   rÙ   )rY   rj   r2   r2   r3   rÉ   Ü  s
    


zTrader.display_allc             C   s,   | j  td|f  ¡ |  |¡}| jj| S )Nz ::_get_portfolio: accountCode=%s)rN   r}   r~   r„   rV   Z
portfolioQ)rY   rj   r’   r2   r2   r3   Ú_get_portfolioã  s    
zTrader._get_portfolioÚvaluec             C   sˆ   | j  td||f  ¡ |  |¡}|dkr0d}n|dkr>d}n|dkrJd}| j |||¡}|dk	rf|S | j  td	||f  ¡ tƒ  dS )
u¥-  
        :param field: string or list of string of the following field names. IB and TD may not have the same fields available.
                        Quantopian values of portfolio_value, cash, position_value are accepted. here.
        :param meta: NotImplemented 20200819. string. Option=['value', 'currency']. Other than "value", IB will callback currency. See broker_client_factory::CallBacks::updateAccountValue
        :param accountCode:
        :return: float or string depending on field name

        TD Ameritrade: NetLiquidation, GrossPositionValue, TotalCashValue, BuyingPower, AvailableFunds
        All of the following fields defined by IB can be used for this method
        https://interactivebrokers.github.io/tws-api/interfaceIBApi_1_1EWrapper.html#ae15a34084d9f26f279abd0bdeab1b9b5
        AccountCode â€” The account ID number
        AccountOrGroup â€” "All" to return account summary data for all accounts, or set to a specific Advisor Account Group name that has already been created in TWS Global Configuration
        AccountReady â€” For internal use only
        AccountType â€” Identifies the IB account structure
        AccruedCash â€” Total accrued cash value of stock, commodities and securities
        AccruedCash-C â€” Reflects the current's month accrued debit and credit interest to date, updated daily in commodity segment
        AccruedCash-S â€” Reflects the current's month accrued debit and credit interest to date, updated daily in security segment
        AccruedDividend â€” Total portfolio value of dividends accrued
        AccruedDividend-C â€” Dividends accrued but not paid in commodity segment
        AccruedDividend-S â€” Dividends accrued but not paid in security segment
        AvailableFunds â€” This value tells what you have available for trading
        AvailableFunds-C â€” Net Liquidation Value - Initial Margin
        AvailableFunds-S â€” Equity with Loan Value - Initial Margin
        Billable â€” Total portfolio value of treasury bills
        Billable-C â€” Value of treasury bills in commodity segment
        Billable-S â€” Value of treasury bills in security segment
        BuyingPower â€” Cash Account: Minimum (Equity with Loan Value, Previous Day Equity with Loan Value)-Initial Margin, Standard Margin Account: Minimum (Equity with Loan Value, Previous Day Equity with Loan Value) - Initial Margin *4
        CashBalance â€” Cash recognized at the time of trade + futures PNL
        CorporateBondValue â€” Value of non-Government bonds such as corporate bonds and municipal bonds
        Currency â€” Open positions are grouped by currency
        Cushion â€” Excess liquidity as a percentage of net liquidation value
        DayTradesRemaining â€” Number of Open/Close trades one could do before Pattern Day Trading is detected
        DayTradesRemainingT+1 â€” Number of Open/Close trades one could do tomorrow before Pattern Day Trading is detected
        DayTradesRemainingT+2 â€” Number of Open/Close trades one could do two days from today before Pattern Day Trading is detected
        DayTradesRemainingT+3 â€” Number of Open/Close trades one could do three days from today before Pattern Day Trading is detected
        DayTradesRemainingT+4 â€” Number of Open/Close trades one could do four days from today before Pattern Day Trading is detected
        EquityWithLoanValue â€” Forms the basis for determining whether a client has the necessary assets to either initiate or maintain security positions
        EquityWithLoanValue-C â€” Cash account: Total cash value + commodities option value - futures maintenance margin requirement + minimum (0, futures PNL) Margin account: Total cash value + commodities option value - futures maintenance margin requirement
        EquityWithLoanValue-S â€” Cash account: Settled Cash Margin Account: Total cash value + stock value + bond value + (non-U.S. & Canada securities options value)
        ExcessLiquidity â€” This value shows your margin cushion, before liquidation
        ExcessLiquidity-C â€” Equity with Loan Value - Maintenance Margin
        ExcessLiquidity-S â€” Net Liquidation Value - Maintenance Margin
        ExchangeRate â€” The exchange rate of the currency to your base currency
        FullAvailableFunds â€” Available funds of whole portfolio with no discounts or intraday credits
        FullAvailableFunds-C â€” Net Liquidation Value - Full Initial Margin
        FullAvailableFunds-S â€” Equity with Loan Value - Full Initial Margin
        FullExcessLiquidity â€” Excess liquidity of whole portfolio with no discounts or intraday credits
        FullExcessLiquidity-C â€” Net Liquidation Value - Full Maintenance Margin
        FullExcessLiquidity-S â€” Equity with Loan Value - Full Maintenance Margin
        FullInitMarginReq â€” Initial Margin of whole portfolio with no discounts or intraday credits
        FullInitMarginReq-C â€” Initial Margin of commodity segment's portfolio with no discounts or intraday credits
        FullInitMarginReq-S â€” Initial Margin of security segment's portfolio with no discounts or intraday credits
        FullMaintMarginReq â€” Maintenance Margin of whole portfolio with no discounts or intraday credits
        FullMaintMarginReq-C â€” Maintenance Margin of commodity segment's portfolio with no discounts or intraday credits
        FullMaintMarginReq-S â€” Maintenance Margin of security segment's portfolio with no discounts or intraday credits
        FundValue â€” Value of funds value (money market funds + mutual funds)
        FutureOptionValue â€” Real-time market-to-market value of futures options
        FuturesPNL â€” Real-time changes in futures value since last settlement
        FxCashBalance â€” Cash balance in related IB-UKL account
        GrossPositionValue â€” Gross Position Value in securities segment
        GrossPositionValue-S â€” Long Stock Value + Short Stock Value + Long Option Value + Short Option Value
        IndianStockHaircut â€” Margin rule for IB-IN accounts
        InitMarginReq â€” Initial Margin requirement of whole portfolio
        InitMarginReq-C â€” Initial Margin of the commodity segment in base currency
        InitMarginReq-S â€” Initial Margin of the security segment in base currency
        IssuerOptionValue â€” Real-time mark-to-market value of Issued Option
        Leverage-S â€” GrossPositionValue / NetLiquidation in security segment
        LookAheadNextChange â€” Time when look-ahead values take effect
        LookAheadAvailableFunds â€” This value reflects your available funds at the next margin change
        LookAheadAvailableFunds-C â€” Net Liquidation Value - look ahead Initial Margin
        LookAheadAvailableFunds-S â€” Equity with Loan Value - look ahead Initial Margin
        LookAheadExcessLiquidity â€” This value reflects your excess liquidity at the next margin change
        LookAheadExcessLiquidity-C â€” Net Liquidation Value - look ahead Maintenance Margin
        LookAheadExcessLiquidity-S â€” Equity with Loan Value - look ahead Maintenance Margin
        LookAheadInitMarginReq â€” Initial margin requirement of whole portfolio as of next period's margin change
        LookAheadInitMarginReq-C â€” Initial margin requirement as of next period's margin change in the base currency of the account
        LookAheadInitMarginReq-S â€” Initial margin requirement as of next period's margin change in the base currency of the account
        LookAheadMaintMarginReq â€” Maintenance margin requirement of whole portfolio as of next period's margin change
        LookAheadMaintMarginReq-C â€” Maintenance margin requirement as of next period's margin change in the base currency of the account
        LookAheadMaintMarginReq-S â€” Maintenance margin requirement as of next period's margin change in the base currency of the account
        MaintMarginReq â€” Maintenance Margin requirement of whole portfolio
        MaintMarginReq-C â€” Maintenance Margin for the commodity segment
        MaintMarginReq-S â€” Maintenance Margin for the security segment
        MoneyMarketFundValue â€” Market value of money market funds excluding mutual funds
        MutualFundValue â€” Market value of mutual funds excluding money market funds
        NetDividend â€” The sum of the Dividend Payable/Receivable Values for the securities and commodities segments of the account
        NetLiquidation â€” The basis for determining the price of the assets in your account
        NetLiquidation-C â€” Total cash value + futures PNL + commodities options value
        NetLiquidation-S â€” Total cash value + stock value + securities options value + bond value
        NetLiquidationByCurrency â€” Net liquidation for individual currencies
        OptionMarketValue â€” Real-time mark-to-market value of options
        PASharesValue â€” Personal Account shares value of whole portfolio
        PASharesValue-C â€” Personal Account shares value in commodity segment
        PASharesValue-S â€” Personal Account shares value in security segment
        PostExpirationExcess â€” Total projected "at expiration" excess liquidity
        PostExpirationExcess-C â€” Provides a projected "at expiration" excess liquidity based on the soon-to expire contracts in your portfolio in commodity segment
        PostExpirationExcess-S â€” Provides a projected "at expiration" excess liquidity based on the soon-to expire contracts in your portfolio in security segment
        PostExpirationMargin â€” Total projected "at expiration" margin
        PostExpirationMargin-C â€” Provides a projected "at expiration" margin value based on the soon-to expire contracts in your portfolio in commodity segment
        PostExpirationMargin-S â€” Provides a projected "at expiration" margin value based on the soon-to expire contracts in your portfolio in security segment
        PreviousDayEquityWithLoanValue â€” Marginable Equity with Loan value as of 16:00 ET the previous day in securities segment
        PreviousDayEquityWithLoanValue-S â€” IMarginable Equity with Loan value as of 16:00 ET the previous day
        RealCurrency â€” Open positions are grouped by currency
        RealizedPnL â€” Shows your profit on closed positions, which is the difference between your entry execution cost and exit execution costs, or (execution price + commissions to open the positions) - (execution price + commissions to close the position)
        RegTEquity â€” Regulation T equity for universal account
        RegTEquity-S â€” Regulation T equity for security segment
        RegTMargin â€” Regulation T margin for universal account
        RegTMargin-S â€” Regulation T margin for security segment
        SMA â€” Line of credit created when the market value of securities in a Regulation T account increase in value
        SMA-S â€” Regulation T Special Memorandum Account balance for security segment
        SegmentTitle â€” Account segment name
        StockMarketValue â€” Real-time mark-to-market value of stock
        TBondValue â€” Value of treasury bonds
        TBillValue â€” Value of treasury bills
        TotalCashBalance â€” Total Cash Balance including Future PNL
        TotalCashValue â€” Total cash value of stock, commodities and securities
        TotalCashValue-C â€” CashBalance in commodity segment
        TotalCashValue-S â€” CashBalance in security segment
        TradingType-S â€” Account Type
        UnrealizedPnL â€” The difference between the current market value of your open positions and the average cost, or Value - Average Cost
        WarrantValue â€” Value of warrants
        WhatIfPMEnabled â€” To check projected margin requirements under Portfolio Margin model
        z,::show_account_info: field=%s accountCode=%sr=   rÛ   Zpositions_valuerÜ   ZcashrÚ   NzD::show_account_info: EXIT, field=%s is not accessible accountCode=%s)rN   r‰   r~   r„   rQ   rÝ   rt   r   )rY   r¸   Úmetarj   r’   rÅ   r2   r2   r3   Úshow_account_infoè  s    |
zTrader.show_account_infoc             C   s.   | j  td ¡ |  |¡}t| j |¡ƒdkS )Nz::hold_any_positionr   )rN   r‰   r~   r„   rÒ   rQ   r•   )rY   rj   r’   r2   r2   r3   Úhold_any_positionr  s    
zTrader.hold_any_positionr8   z
US/Easternc          
   C   s´   |	t jkr2| j |	| j¡}| ||  ¡ ||||¡S | jrb| j |¡ | jj	||||||||
d}n(| j
 |¡ | j
j	||||||||
d}t|ƒdkrª| j d¡ t ¡ S t||ƒS )a   

        :param followUp:
        :param dataProviderName: only works for DataProviderName.YAHOO
        :param security: Security
        :param barSize: string barSize can be any of the following values(string) 1 sec, 5 secs,15 secs,30 secs,1 min,2 mins,3 mins,5 mins,15 mins,30 mins,1 hour,1 day
        :param goBack: string
        :param endTime: default value is '', IB server deems '' as the current server time. If user wants to supply a value, it must be a datetime with timezone
        :param whatToShow: string See IB documentation for choices TRADES,MIDPOINT,BID,ASK,BID_ASK,HISTORICAL_VOLATILITY,OPTION_IMPLIED_VOLATILITY
        :param useRTH: int 1=within regular trading hours, 0=ignoring RTH
        :param waitForFeedbackInSeconds:
        :param timezoneOfReturn: the index of the returned DataFrame will be adjusted
        :return: a DataFrame, keyed by a datetime with timezone UTC, columns = ['open', 'high', 'low', 'close', 'volume'] The latest time record at the bottom of the dateFrame.
        )ÚfollowUpr   z™There is no any historical data available from the Broker right now. Please double check the input parameters to the function of request_historical_data.)r   ÚYAHOO_FINANCErS   Úget_dataProvider_by_namerB   Ú%provide_hist_from_a_true_dataProviderrÂ   rR   r»   Úget_historical_datarQ   rÒ   rN   rÇ   ÚpdÚ	DataFramer#   )rY   r1   ÚbarSizeÚgoBackÚendTimeÚ
whatToShowÚuseRTHr¶   ÚtimezoneOfReturnÚdataProviderNamerä   ÚdataProviderÚhistr2   r2   r3   Úrequest_historical_dataw  s    
zTrader.request_historical_datac             C   s:   | j  td||f  ¡ | j |¡ | j || j| |¡S )Nz,::show_real_time_price: security=%s param=%s)rN   r}   r~   rR   r»   Úget_real_time_pricerU   )rY   r1   Úparamrä   r2   r2   r3   Úshow_real_time_price˜  s    zTrader.show_real_time_pricec             C   s8   | j  td||f  ¡ | j |¡ | j || j| ¡S )zÂ
        Show the timestamp of a field of a security
        :param security: a security
        :param param: the field name
        :return: the timestamp when the IB callback happens
        z&::show_timestamp: security=%s param=%s)rN   r}   r~   rR   r»   Úget_timestamprU   )rY   r1   rö   r2   r2   r3   Úshow_timestampž  s    zTrader.show_timestampc             C   sD   | j  tdt|ƒt|ƒf  ¡ | j |¡ | jj|| j| |dS )Nz+::show_real_time_size: security=%s param=%s)rä   )rN   r}   r~   r<   rR   r»   Úget_real_time_sizerU   )rY   r1   rö   rä   r2   r2   r3   Úshow_real_time_size©  s     zTrader.show_real_time_sizec             C   sˆ   t |tƒr.| j td|f  ¡ | j |¡ nVt |tƒrP| j td ¡ t	ƒ  n4t |t
ƒr„| j td| ¡ f  ¡ | j | ¡ ¡ dS )z+
        function to cancel orders
        z::cancel_order: ibpyOrderId=%sz,::cancel_order: ibpyOrderId must be a stringN)rn   r<   rN   r‰   r~   rQ   r§   r9   rt   r   r"   ÚgetIbpyOrderId)rY   rŸ   r2   r2   r3   r§   ®  s    


zTrader.cancel_orderc             C   sh   | j  ¡ }|  |¡}|dkr&t|ƒ}ndt|ƒ }| j  |¡ t||||||  ¡ |||||	|
|d}|S )NÚBUYéÿÿÿÿ)ÚocaGroupÚocaTypeÚtransmitÚparentIdÚorderRefÚ
outsideRthÚhidden)rQ   Úuse_next_idr„   r:   r»   r   rÂ   )rY   Úactionr‘   r1   ÚorderDetailsrÿ   r   r  r  r  r  r  rj   Úint_orderIdr’   rÅ   r2   r2   r3   r   ¼  s    


zTrader.create_orderc
             C   sv   | j  td| ¡ ||||||f  ¡ |  |¡}
| j ¡ }| j |¡ t||
||||  	¡ |||d	}| jj
||	|dS )NzZ::order: security=%s amount=%s style=%s orderRef=%s accountCode=%s outsideRth=%s hidden=%s)r  r  r  )rä   r¶   )rN   r‰   r~   r   r„   rQ   r  r»   r   rÂ   Úplace_order)rY   r1   r‘   Ústyler  rj   r  r  r¶   rä   r’   r	  ÚibridgePyOrderr2   r2   r3   ÚorderÊ  s    &


zTrader.orderc             C   sn   | j  td ¡ |  |¡}|  |¡ | j |d¡}|  |d¡}	t|||	d| j	ƒ}
| j
|t|
| ƒ||||dS )Nz::order_percentrÛ   r$   r   )r‘   r  r  rj   rä   )rN   r}   r~   r„   Ú_check_percent_validityrQ   rÝ   r÷   r@   rX   r  r9   )rY   r1   Úpercentr  r  rä   rj   r’   r=   r>   ÚtargetSharer2   r2   r3   Úorder_percentÕ  s    

zTrader.order_percentc             C   s.   |dks|dk r*| j  d|› d¡ tƒ  d S )Ng      ð?g      ð¿zorder_percent: EXIT, percent=z! outside the range of [-1.0, 1.0])rN   rt   r   )rY   r  r2   r2   r3   r  à  s    zTrader._check_percent_validityc       
      C   s†   | j  td| ¡ |f  ¡ |  |¡}| j||d}|j}	||	krh| j|tt	|ƒt	|	ƒ ƒ||||dS | j  td|f  ¡ dS d S )Nz%::order_target: security=%s amount=%s)rj   )r‘   r  r  rj   rä   z&::order_target: %s No action is neededÚNoOrderPlaced)
rN   r‰   r~   r   r„   r   r‘   r  r<   r   )
rY   r1   r‘   r  r  rä   rj   r’   ÚpositionÚholdr2   r2   r3   r—   å  s    
zTrader.order_targetc             C   s¬   |   |¡}|  |¡ | j |d¡}|  |d¡}	|  |¡}
t |	¡r^| j 	d| 
¡ f ¡ tƒ  |	dkr„| j 	d|	| 
¡ f ¡ tƒ  t|||	|
| jƒ}| j||||||dS )NrÛ   r$   zxorder_target_percent: EXIT, No real time price is available right now. Market closed? real_time_price is NaN security=%sg        ztorder_target_percent: EXIT, No real time price is available right now. Market closed? real_time_price=%s security=%s)r‘   r  r  rj   rä   )r„   r  rQ   rÝ   r÷   r”   ÚmathÚisnanrN   rt   r   r   r@   rX   r—   )rY   r1   r  r  r  rä   rj   r’   r=   r>   r?   r  r2   r2   r3   Úorder_target_percentó  s    




zTrader.order_target_percentc       	      C   sD   | j  td ¡ |  |¡}t||  |d¡ ƒ}| j||||||dS )Nz::order_target_valuer$   )r‘   r  r  rj   rä   )rN   r}   r~   r„   r9   r÷   r—   )	rY   r1   rà   r  r  rä   rj   r’   r  r2   r2   r3   Úorder_target_value  s
    

zTrader.order_target_valuec       	      C   sD   | j  td ¡ |  |¡}t||  |d¡ ƒ}| j||||||dS )Nz::order_valuer$   )r‘   r  r  rj   rä   )rN   r}   r~   r„   r9   r÷   r  )	rY   r1   rà   r  r  rä   rj   r’   r  r2   r2   r3   Úorder_value  s
    

zTrader.order_valuec          
   C   sb   | j  |¡ ttj ¡ ƒ}|  |¡}| j  ¡ }t||||||  	¡ ||d}	| j  ¡ }
||	|
||fS )N)rÿ   r  )
rQ   r»   r<   ÚdtÚdatetimeÚnowr„   r  r   rÂ   )rY   r1   r‘   r  r  rj   rÿ   r’   Úint_parentOrderIdÚparentOrderÚint_slOrderIdr2   r2   r3   Ú_build_order_helper  s    



zTrader._build_order_helperÚDAYc          
   C   s„   |   |||||¡\}}	}
}}t|
||| t||d|  ¡ ||d}d|	jd< ||jd< d|jd< | jj|	dd}| j |¡}||fS )N)Útif)rÿ   r  Fr  r  T)rä   )r   r   r   rÂ   ÚrequestedOrderrQ   r
  )rY   r1   r‘   ÚstopLossPricer  r"  r  rj   r’   r  r  rÿ   r  ÚslOrderÚstr_parentOrderIdÚstr_slOrderIdr2   r2   r3   Úplace_order_with_stoploss&  s    


z Trader.place_order_with_stoplossc          
   C   s„   |   |||||¡\}}	}
}}t|
||| t||d|  ¡ ||d}d|	jd< ||jd< d|jd< | jj|	dd}| j |¡}||fS )N)r"  )rÿ   r  Fr  r  T)rä   )r   r   r   rÂ   r#  rQ   r
  )rY   r1   r‘   ÚtakeProfitPricer  r"  r  rj   r’   r  Úint_tpOrderIdrÿ   r  ÚtpOrderr&  Ústr_tpOrderIdr2   r2   r3   Úplace_order_with_takeprofit8  s    


z"Trader.place_order_with_takeprofitc
          
   C   s  | j  |¡ |dkr"ttj ¡ ƒ}|  |¡}
| j  ¡ }t||
||||  	¡ ||	d}| j  ¡ }t||
|| t
||d|  	¡ ||	d}| j  ¡ }t||
|| t||d|  	¡ ||	d}d|jd< ||jd< ||jd< d|jd< d|jd< | j j|dd}| j j|dd}| j  |¡}|||fS )	a@  
        # https://developer.tdameritrade.com/content/place-order-samples Not implemented for TD yet
        orderStatus of parentOrder is Submitted
        orderStatus of stoplossOrder and takeprofitOrder is PreSubmitted.
        !!! All three orders will cost margin, which means less margin for other trades.
        N)rÿ   r  )r"  Fr  r  T)rä   )rQ   r»   r<   r  r  r  r„   r  r   rÂ   r   r   r#  r
  )rY   r1   r‘   r$  r)  r  r"  rj   rÿ   r  r’   r  r  r*  r+  r  r%  r&  r,  r'  r2   r2   r3   Ú$place_order_with_stoploss_takeprofitJ  s0    











z+Trader.place_order_with_stoploss_takeprofitc             C   s0   g }x&|D ]}| j j|dd}| |¡ q
W |S )NF)rä   )rQ   r
  r˜   )rY   ZlegListrÅ   r  rŸ   r2   r2   r3   Úplace_combination_orderso  s
    
zTrader.place_combination_ordersc	       
      C   sô   | j  td|f  ¡ | j |¡}	|	jtjtjgkrÐ|d k	rF||	j	d< |d k	rX||	j	d< |d k	rj||	j	d< |d k	r|||	j	d< |d k	rŽ||	j	d< |d k	r ||	j	d< |d k	r²||	j	d< | j 
t||	j|	j	tjƒ¡ n | j  td	||	jf  ¡ tƒ  d S )
Nz ::modify_order: ibpyOrderId = %sÚtotalQuantityÚlmtPriceÚauxPricer"  r  rÿ   r   z;::modify_order: Cannot modify ibpyOrderId=%s orderStatus=%s)rN   r‰   r~   rQ   Ú	get_orderr£   r   ÚPRESUBMITTEDÚ	SUBMITTEDr  rÈ   r    Úcontractr   ÚDO_NOT_FOLLOW_UPrt   r   )
rY   rŸ   ZnewQuantityZnewLimitPriceZnewStopPriceZnewTifZnewOrderRefZnewOcaGroupZ
newOcaTypeZcurrentOrderr2   r2   r3   Úmodify_orderv  s*    






zTrader.modify_orderc             C   s   | j  |¡jS )zE
        ibpyOrderId is unique for any orders in any session
        )rQ   r3  r£   )rY   rŸ   r2   r2   r3   Úget_order_status  s    zTrader.get_order_statusc             C   s^   | j  td||f  ¡ t|tƒs>| j  td|f  ¡ tƒ  |dkrJdS | j |||¡ dS )a  
        IBridgePy automatically follow up on the status of requests sent to brokers and terminate if the request is not
        confirmed with in 30 seconds. When placing order, IBridgePy only checks if the order is delivered to brokers but
        does not specifically check the order status. To specifically follow up on specific order status,
        order_status_monitor is used.
        :param ibpyOrderId: str
        :param target_status: either str or list[str]
        :param waitingTimeInSeconds: int
        :return: None
        z7::order_status_monitor: ibpyOrderId=%s target_status=%sz=::order_status_monitor: EXIT, ibpyOrderId=%s must be a stringr  N)	rN   r}   r~   rn   r<   rt   r   rQ   r™   )rY   rŸ   Útarget_statusÚwaitingTimeInSecondsr2   r2   r3   r™   •  s    
zTrader.order_status_monitorc             C   s   |   |¡}| j |¡S )N)r„   rQ   Úget_all_open_orders)rY   rj   r’   r2   r2   r3   r<  ¨  s    
zTrader.get_all_open_ordersc             C   s"   | j  td|f  ¡ | j |¡S )z“
        tested at integ_test_cancel_all_order.py
        :param ibpyOrderId:
        :return: broker_factory::records_def::IbridgePyOrder
        z::get_order: ibpyOrderId=%s)rN   r‰   r~   rQ   r3  )rY   rŸ   r2   r2   r3   r3  ¬  s    zTrader.get_orderc       	      C   s¨   | j  td ¡ |  |¡}| j |¡}|dkrxi }xp|D ]:}t|jƒ}t||ƒ}|dkrd|g||< q8||  	|¡ q8W n,g }x&|D ]}t
t|jƒ|ƒr‚| 	|¡ q‚W |S )aV  
        OrderStatus = APIPENDING, PENDINGSUBMIT, PENDINGCANCEL, PRESUBMITTED, SUBMITTED
        :param security: IBridgePy::quantopian::Security
        :param accountCode: string
        :return: a list of models::Order::IbridgePyOrder when security is not None. Otherwise, a dict: key=security, value=models::Order::IbridgePyOrder
        z::get_open_ordersN)rN   r‰   r~   r„   rQ   r<  r   r6  r4   r˜   r   )	rY   r1   rj   r’   Z	orderListrÅ   r  ZsecurityAsKeyZsecurityInListr2   r2   r3   Úget_open_ordersµ  s     




zTrader.get_open_ordersc             C   sJ   | j  td ¡ |  |¡}| j |¡}i }x|D ]}|  |¡||< q0W |S )a/  
        For Web-api-based brokers, it return all orders that are returned from the broker.
        But brokers may not return all orders. For example, IB returns only OPEN orders.
        :param accountCode:
        :return: dictionary keyed=ibpyOrderId value= {@models::Order::IbridgePyOrder}
        z::get_all_orders)rN   r‰   r~   r„   rQ   r¢   r3  )rY   rj   r’   r   rÅ   rŸ   r2   r2   r3   r¢   Ð  s    

zTrader.get_all_ordersc             C   s&   | j  td ¡ |  |¡}| j |¡S )z{

        :param accountCode: string
        :return: dictionary, keyed by Security object, value = PositionRecord
        z::get_all_positions)rN   r‰   r~   r„   rQ   r•   )rY   rj   r’   r2   r2   r3   r•   ß  s    
zTrader.get_all_positionsc             C   s.   | j  td|f  ¡ |  |¡}| j ||¡S )zÍ

        :param security:
        :param accountCode:
        :return: models::Position::PositionRecord If there is no position for the security, return a PositionRecord .amount=0 .cost_basis=0.0
        z::get_position: security=%s)rN   r‰   r~   r„   rQ   r   )rY   r1   rj   r’   r2   r2   r3   r   é  s    
zTrader.get_positionc             C   s¦   |   ¡  | j¡}| j td|f  ¡ xz| jD ]p}t|j|j	dƒr.t|j
|jdƒr.t|j|jdƒr.t|j| j |¡dƒr.t|j| j |¡dƒr.| | j| j¡ q.W d S )Nz::_check_schedules: timeNow=%sÚ
hourMinuteÚ	monthWeek)rÂ   r‹   rF   rN   r}   r~   ÚscheduledFunctionListr   ÚonHourÚhourÚonMinuteÚminuteÚonSecondÚsecondÚonNthMonthDayrO   Únth_trading_day_of_monthÚonNthWeekDayÚnth_trading_day_of_weekÚfuncrV   rW   )rY   rŒ   Úctr2   r2   r3   rÍ   ÷  s    zTrader._check_schedulesc             C   sL  d}d}d}| j  td ¡ |dkr2d}d}d}nä|\}}	}
}|d |	 }|
d | }|jdksj|jdkrÚ|jdkrŠ||jd  |j }n||jd  |j }x|dk r²|d7 }q W |d }t|d ƒ}t|d ƒ}d}n<|jd	krø|j}|j}|j}n| j  td
|jf  ¡ t	ƒ  |dkr@t
||||d}| j |¡ dS |jdkrlt
||||d}| j |¡ dS |jdkr |j}t
|||||d}| j |¡ dS |jdkrÚ|j d }t
|||||d}| j |¡ dS |jdkr|j}t
|||||d}| j |¡ dS |jdkrH|j d }t
|||||d}| j |¡ dS dS )aF  
        ONLY time_rule.spot_time depends on
        :param func: the function to be run at sometime
        :param date_rule: IBridgePy::quantopian::date_rule
        :param time_rule: BridgePy::quantopian::time_rule
        :param calendar: typical market open close time
        :return: self.scheduledFunctionList
        Nz::schedule_functionÚanyé<   Úmarket_openÚmarket_closer   i   Ú	spot_timez=::schedule_function: EXIT, cannot handle time_rule.version=%s)rA  rC  rE  rK  Ú	every_dayÚ
week_start)rI  rA  rC  rE  rK  Úweek_endr8   Úmonth_start)rG  rA  rC  rE  rK  Ú	month_end)rN   r‰   r~   ÚversionrB  rD  r9   rF  rt   r   r   r@  r˜   ÚweekDayÚmonthDay)rY   rK  Z	date_ruleZ	time_ruleÚcalendarrA  rC  rE  ZmarketOpenHourZmarketOpenMinuteZmarketCloseHourZmarketCloseMinuteZ
marketOpenZmarketCloseÚtmpÚ	startTimerI  rG  r2   r2   r3   Úschedule_function  s    



zTrader.schedule_functionc             C   s   t | ƒ}|S )N)r	   )rÓ   r1   r2   r2   r3   r   d  s    zTrader.symbolc             G   s&   g }x|D ]}|  |  |¡¡ q
W |S )N)r˜   r   )rY   ÚargsrÅ   Úitemr2   r2   r3   Úsymbols  s    
zTrader.symbolsc             C   sÎ   | j  td ¡ |  |¡}|  |¡}d}x’|D ]Š}|| }|jtjtjgkr.| 	d¡}|t
jkrr||j|j 7 }q.|t
jkrŽ||j|j 7 }q.|t
jkr.||j|j 7 }||j|j 7 }q.W | j |d¡| S )aK  
        it is deprecated because different users have different account type(cash vs margin). If they trade options, futures
        and others, the way to calculated the amount to trade is different. IBridgePy should not do it for users and users
        should know which value they should use, especially for IB users.
        z&::calculate_cash_for_trade_deprecated:g        Ú	orderTypeÚAvailableFunds)rN   r‰   r~   r„   r¢   r£   r   r5  r4  Úget_value_by_tagr   ÚLMTÚlimitr‘   ÚSTPÚstopÚSTP_LMTrQ   rÝ   )rY   rj   r’   Z	orderDictZcashOccupiedrŸ   r  ra  r2   r2   r3   Ú#calculate_cash_for_trade_deprecated…  s     






z*Trader.calculate_cash_for_trade_deprecatedc             C   sR  | j  td ¡ |  |¡}|  |¡}g }t| ¡ ƒ}xô|D ]ì}	t|	|ƒs:|  |	|¡j	}
t
|
ƒdkrÀ|  |	d¡}t|d|  ƒ}| j  td||f  ¡ | j|	tdt
|
ƒ ƒt|tjd|d}n\|  |	d	¡}t|d|  ƒ}| j  td
||f  ¡ | j|	tdt
|
ƒ ƒt|tjd|d}| |¡ q:W |rNx|D ]}|  |tj¡ q6W d S )Nz::close_all_positions_LMT:r   r%   g      ð?z<::close_all_positions_LMT: bid_price=%s, sellAtLimitPrice=%srþ   )r"  )r  rj   r$   z;::close_all_positions_LMT: ask_price=%s, buyAtLimitPrice=%s)rN   r‰   r~   r„   r•   ro   r–   r7   r   r‘   r   r÷   r   rÇ   r  r<   r   r   ÚGTCr˜   r™   r   rš   )rY   Úls_excludeSecuritiesÚ	advantager›   rj   r’   rœ   r   rž   r1   Úholding_quantityr%   Ú
limitPricerŸ   r$   r2   r2   r3   Úclose_all_positions_LMT  s2    





zTrader.close_all_positions_LMTc          	   C   sÂ  |   |¡}tj ¡ }t|ƒ}|dkr:| jg |d|d dS | j d¡ | j| ¡ |d|d | j d¡ i }i }	x€|D ]x}
|  	|
|¡j
}||
 }t|ƒt|ƒk r¶t|ƒt|ƒ ||
< qvt|ƒt|ƒkrÜt|ƒt|ƒ |	|
< qv| j d|
f ¡ qvW | j dt|ƒf ¡ | j d	t|	ƒf ¡ g }xT|D ]L}
|  |
d
¡}| j|
||
 tt|d|  ƒtjdtj|d}| |¡ q(W x|D ]}|  |ddg¡ q~W g }d}xt|	ƒdkr¨tj ¡ |  ¡ dk r¨g }| jd|d}t|| ƒdkr| j td ¡ t d¡ |  |  ¡ ¡ q¤|}| j td|f  ¡ |   ¡  x&|	D ]}
|  |
d¡}|	|
 }t!|t"|| ƒƒ}t|d|  ƒ}|dkryh| j|
|t|tjd|tjd}| |¡ |	|
  |8  < t|ƒt|ƒ|  }| j td|f  ¡ W n& t#k
r   | j td ¡ Y nX n,|dk rH| j $td||||f  ¡ t%ƒ  |	|
 dkrD| |
¡ qDW x|D ]}
|	|
= qlW t d¡ | j td ¡ |  |  ¡ ¡ q¤W | j td ¡ || S )a  
        Used for IB only because processMessage() will be very slow for WebAPI based brokers.
        :param sellAdvantage:
        :param buyAdvantage: take advantages when place buy orders at ask_price * (1 - bugAdvantage), positive == take advantage. negative == disadvantage.
        :param accountCode:
        :param traderDecisions: dict key=security value=target number of share
        :return:
        r   F)rk  rl  r›   rj   Nz3Start to sell securities not in the traderDecisionsz6Finished to sell securities not in the traderDecisionszNo action for security=%szsellSecurityDict=%szbuySecurityDict=%sr%   g      ð?)r"  )r  rä   rj   ÚFilledÚ	Submittedg        i,  rb  )rj   g®Gáz®ï?zl::rebalance_portfolio: available_fund has not been updated. Do not continue to place orders. Sleep 3 secondsé   z(::rebalance_portfolio: available_fund=%sr$   )r  rj   rä   z0::rebalance_portfolio: virtual available_fund=%sz?::rebalance_portfolio: Not enough fund but it is ok to continueza::rebalance_portfolio: EXIT, purchase_amount=%s target_quantity=%s available_fund=%s ask_price=%sz+::rebalance_portfolio: waited for 3 secondsz ::rebalance_portfolio: completed)&r„   r  r  r  rÒ   ro  rN   rÇ   r–   r   r‘   r   r‰   r
   r÷   r  r   r   r   rj  r   r7  r˜   r™   Útotal_secondsrâ   r:   r~   ÚtimeÚsleepr¾   rÂ   rÉ   Úminr9   r!   rt   r   )rY   ZtraderDecisionsZbuyAdvantageZsellAdvantagerj   r’   r\  ÚcountZsellSecurityDictZbuySecurityDictr1   rm  Ztarget_quantityZsellOrderIdsr%   rŸ   ÚoidZbuyOrderIdsZprevious_available_fundZtoBeDeletedZavailable_fundr$   Zpurchase_amountrn  r2   r2   r3   Úrebalance_portfolioÅ  s–    	




*






zTrader.rebalance_portfolioc             C   s   | j  |  ¡ ¡S )N)rO   ÚisTradingDayrÂ   )rY   r2   r2   r3   rz  :  s    zTrader.isTradingDayc             C   s   | j  |  ¡ ¡S )N)rO   ÚisEarlyCloserÂ   )rY   r2   r2   r3   r{  =  s    zTrader.isEarlyClosec             O   s   | j j||Ž d S )N)rM   Úrecord)rY   r^  rº   r2   r2   r3   r|  @  s    zTrader.recordc             C   s   | j  |||¡ d S )N)rP   Ú
send_email)rY   Ú
emailTitleÚ	emailBodyÚtoEmailr2   r2   r3   r}  C  s    zTrader.send_emailc             C   s6   | j  t› d|› d|› ¡ | j |¡ | j ||¡S )Nz'::get_5_second_real_time_bar: security=z
 tickType=)rN   r}   r~   rR   r»   rQ   Úget_5_second_real_time_bar)rY   r1   ÚtickTyper2   r2   r3   r  F  s    z!Trader.get_5_second_real_time_bar)N)rƒ   )Trƒ   )Trƒ   )rƒ   )	rª   r]   r]   r]   r«   r]   r]   r]   r¬   )r¬   )r¬   )rƒ   )rƒ   )rƒ   )rƒ   )rƒ   )rà   rƒ   )rƒ   )T)T)NNNNr]   FFrƒ   )NNNNNNN)r¬   )rƒ   )Nrƒ   )rƒ   )rƒ   )rƒ   )rƒ   )Trƒ   )r«   r«   rƒ   )N)\r~   Ú
__module__Ú__qualname__rÌ   r   r@  rÀ   rs   rr   rZ   r\   rv   Úpropertyrw   rz   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  r—   r  r  r  r   r(  r-  r.  r/  r8  r9  r™   r<  r3  r=  r¢   r•   r   rÍ   r   ÚUS_EQUITIESr]  Ústaticmethodr   r`  ri  ro  ry  rz  r{  r|  r}  r  r2   r2   r2   r3   rA   M   sÂ   $)
	



 





(




 
 

 



$ 


	




\

(
u
rA   )Nr  r  r  rt  Úsysr   Úpandasré   rÃ   Údecimalr   ÚBasicPyLib.BasicToolsr   Ú	IBridgePyr   ÚIBridgePy.IbridgepyToolsr   r   r   r	   r
   r   ÚIBridgePy.constantsr   r   r   r   r   ÚIBridgePy.quantopianr   r   r   r   r   ÚIBridgePy.OrderTypesr   r   r   ZIBridgePy.trader_defsr   Ú&broker_client_factory.BrokerClientDefsr   r   r   r   r   r   r    Ú"broker_client_factory.CustomErrorsr!   Úmodels.Orderr"   Ztools.hist_converterr#   ÚTickTypeÚASKÚBIDÚLASTÚOPENÚHIGHÚLOWÚCLOSEÚVOLUMEÚASK_SIZEÚBID_SIZEÚ	LAST_SIZEÚASK_OPTION_COMPUTATIONÚBID_OPTION_COMPUTATIONÚLAST_OPTION_COMPUTATIONÚMODEL_OPTIONÚOPTION_CALL_OPEN_INTERESTÚOPTION_PUT_OPEN_INTERESTrT   r4   r7   r@   ÚobjectrA   r2   r2   r2   r3   Ú<module>   sR    $