Update trades table upon stopping out of a spread so that it includes the closing price and slippage incurred on exit
This commit is contained in:
parent
b6c0738e00
commit
d868192002
@ -11,9 +11,10 @@ from ibkr import Client, OptionLeg
|
|||||||
from ibkr.option_type import CALL, PUT
|
from ibkr.option_type import CALL, PUT
|
||||||
from ibkr.order_action import BUY, SELL
|
from ibkr.order_action import BUY, SELL
|
||||||
|
|
||||||
|
from iron_condor_trade import IronCondorTrade
|
||||||
from options_chain import OptionsChain
|
from options_chain import OptionsChain
|
||||||
from option_type import OptionType
|
from option_type import OptionType
|
||||||
from trades_table import insert_trade
|
from trades_table import insert_trade, update_on_stop_loss
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ load_dotenv()
|
|||||||
# Necessary for monitoring spread prices asynchronously while interacting with the IBKR client.
|
# Necessary for monitoring spread prices asynchronously while interacting with the IBKR client.
|
||||||
nest_asyncio.apply()
|
nest_asyncio.apply()
|
||||||
|
|
||||||
def monitor_spread_price(short_leg: OptionLeg, long_leg: OptionLeg, stop_price: float, client: Client):
|
def monitor_spread_price(trade: IronCondorTrade, short_leg: OptionLeg, long_leg: OptionLeg, stop_price: float, client: Client):
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
Stop loss orders will not execute if trying to sell back a contract with no bid while paper trading.
|
Stop loss orders will not execute if trying to sell back a contract with no bid while paper trading.
|
||||||
Therefore, the spread price must be monitored and the spread manually exited if the stop price is reached.
|
Therefore, the spread price must be monitored and the spread manually exited if the stop price is reached.
|
||||||
@ -60,7 +61,10 @@ def monitor_spread_price(short_leg: OptionLeg, long_leg: OptionLeg, stop_price:
|
|||||||
exit_order = client.submit_option_order(short_leg_exit)
|
exit_order = client.submit_option_order(short_leg_exit)
|
||||||
logging.info('Short leg only exited.')
|
logging.info('Short leg only exited.')
|
||||||
|
|
||||||
logging.info(f'Exit Slippage: {round(exit_order.fill_price - stop_price, 3)}')
|
exit_slippage = round(exit_order.fill_price - stop_price, 3)
|
||||||
|
logging.info(f'Exit Slippage: {exit_slippage}')
|
||||||
|
|
||||||
|
update_on_stop_loss(trade, short_leg.option_type, exit_order.fill_price, exit_slippage)
|
||||||
|
|
||||||
# Unsubscribe from market data updates once the trade has exited.
|
# Unsubscribe from market data updates once the trade has exited.
|
||||||
for leg in [short_leg, long_leg]:
|
for leg in [short_leg, long_leg]:
|
||||||
@ -116,6 +120,7 @@ def _enter_iron_condor(entry_time: datetime):
|
|||||||
logging.info(f'Long Call Strike: {long_call_strike}')
|
logging.info(f'Long Call Strike: {long_call_strike}')
|
||||||
|
|
||||||
ibkr_client = Client()
|
ibkr_client = Client()
|
||||||
|
trade = IronCondorTrade(symbol, credit_target, entry_time, float(getenv('STOP_MULTIPLE')))
|
||||||
|
|
||||||
short_call_leg = OptionLeg(symbol, expiration, short_call_strike, CALL, SELL, sub_symbol)
|
short_call_leg = OptionLeg(symbol, expiration, short_call_strike, CALL, SELL, sub_symbol)
|
||||||
long_call_leg = OptionLeg(symbol, expiration, long_call_strike, CALL, BUY, sub_symbol)
|
long_call_leg = OptionLeg(symbol, expiration, long_call_strike, CALL, BUY, sub_symbol)
|
||||||
@ -123,9 +128,10 @@ def _enter_iron_condor(entry_time: datetime):
|
|||||||
call_spread_order = ibkr_client.submit_spread_order(short_call_leg, long_call_leg)
|
call_spread_order = ibkr_client.submit_spread_order(short_call_leg, long_call_leg)
|
||||||
logging.info(f'Call Spread Mid Price: {call_spread_order.mid_price}')
|
logging.info(f'Call Spread Mid Price: {call_spread_order.mid_price}')
|
||||||
logging.info(f'Call Spread Fill Price: {call_spread_order.fill_price}')
|
logging.info(f'Call Spread Fill Price: {call_spread_order.fill_price}')
|
||||||
logging.info(f'Call Spread Slippage: {call_spread_order.fill_price - call_spread_order.mid_price}')
|
logging.info(f'Call Spread Slippage: {call_spread_order.mid_price - call_spread_order.fill_price}')
|
||||||
|
|
||||||
monitor_spread_price(
|
monitor_spread_price(
|
||||||
|
trade = trade,
|
||||||
short_leg = short_call_leg,
|
short_leg = short_call_leg,
|
||||||
long_leg = long_call_leg,
|
long_leg = long_call_leg,
|
||||||
stop_price = call_spread_order.fill_price * 2,
|
stop_price = call_spread_order.fill_price * 2,
|
||||||
@ -138,16 +144,17 @@ def _enter_iron_condor(entry_time: datetime):
|
|||||||
put_spread_order = ibkr_client.submit_spread_order(short_put_leg, long_put_leg)
|
put_spread_order = ibkr_client.submit_spread_order(short_put_leg, long_put_leg)
|
||||||
logging.info(f'Put Spread Mid Price: {put_spread_order.mid_price}')
|
logging.info(f'Put Spread Mid Price: {put_spread_order.mid_price}')
|
||||||
logging.info(f'Put Spread Fill Price: {put_spread_order.fill_price}')
|
logging.info(f'Put Spread Fill Price: {put_spread_order.fill_price}')
|
||||||
logging.info(f'Put Spread Slippage: {put_spread_order.fill_price - put_spread_order.mid_price}')
|
logging.info(f'Put Spread Slippage: {put_spread_order.mid_price - put_spread_order.fill_price}')
|
||||||
|
|
||||||
monitor_spread_price(
|
monitor_spread_price(
|
||||||
|
trade = trade,
|
||||||
short_leg = short_put_leg,
|
short_leg = short_put_leg,
|
||||||
long_leg = long_put_leg,
|
long_leg = long_put_leg,
|
||||||
stop_price = put_spread_order.fill_price * 2,
|
stop_price = put_spread_order.fill_price * 2,
|
||||||
client = ibkr_client
|
client = ibkr_client
|
||||||
)
|
)
|
||||||
|
|
||||||
insert_trade(symbol, credit_target, entry_time, call_spread_order, put_spread_order)
|
insert_trade(trade, call_spread_order, put_spread_order)
|
||||||
|
|
||||||
# TODO: Add a shutdown hook.
|
# TODO: Add a shutdown hook.
|
||||||
ibkr_client.run_event_loop()
|
ibkr_client.run_event_loop()
|
@ -1,13 +1,13 @@
|
|||||||
from datetime import datetime
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
from backtesting.credit_targeting import iron_condor_strategy
|
from database.trades import get_leg, get_spread, trade, upsert
|
||||||
from database.trades import get_leg, get_spread, upsert
|
|
||||||
from database.trades.action import Action
|
from database.trades.action import Action
|
||||||
from database.trades.option_type import OptionType
|
from database.trades.option_type import OptionType
|
||||||
from ibkr import option_type as IBKROptionType
|
from ibkr import option_type as IBKROptionType
|
||||||
from ibkr.option_order import OptionOrder
|
from ibkr.option_order import OptionOrder
|
||||||
|
|
||||||
|
from iron_condor_trade import IronCondorTrade
|
||||||
|
|
||||||
def translate_action(action_string: str) -> Action:
|
def translate_action(action_string: str) -> Action:
|
||||||
for action in Action:
|
for action in Action:
|
||||||
if action_string == action.value:
|
if action_string == action.value:
|
||||||
@ -37,22 +37,43 @@ def spread(spread_order: OptionOrder) -> dict:
|
|||||||
entry_slippage = round(spread_order.mid_price - spread_order.fill_price, 3)
|
entry_slippage = round(spread_order.mid_price - spread_order.fill_price, 3)
|
||||||
)
|
)
|
||||||
|
|
||||||
def insert_trade(
|
def insert_trade(iron_condor: IronCondorTrade, call_spread_order: OptionOrder, put_spread_order: OptionOrder):
|
||||||
symbol: str,
|
|
||||||
target: float,
|
|
||||||
entry_time: datetime,
|
|
||||||
call_spread_order: OptionOrder,
|
|
||||||
put_spread_order: OptionOrder
|
|
||||||
):
|
|
||||||
|
|
||||||
upsert(
|
upsert(
|
||||||
DataFrame([{
|
DataFrame([{
|
||||||
'Date': datetime.now().date(),
|
'Date': iron_condor.entry_time.date(),
|
||||||
'Symbol': symbol,
|
'Symbol': iron_condor.symbol,
|
||||||
'Strategy': iron_condor_strategy(target),
|
'Strategy': iron_condor.strategy,
|
||||||
'Entry Time': entry_time.replace(tzinfo = None),
|
'Entry Time': iron_condor.entry_time,
|
||||||
'Exit Time': None, # Required.
|
'Exit Time': None, # Required.
|
||||||
'Spreads': [spread(call_spread_order), spread(put_spread_order)],
|
'Spreads': [spread(call_spread_order), spread(put_spread_order)],
|
||||||
'Profit': None # Required.
|
'Profit': None # Required.
|
||||||
}])
|
}])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def update_on_stop_loss(iron_condor: IronCondorTrade, option_type: str, close_price: float, exit_slippage: float):
|
||||||
|
date = iron_condor.entry_time.date()
|
||||||
|
|
||||||
|
trade_record = trade(
|
||||||
|
date = date,
|
||||||
|
symbol = iron_condor.symbol,
|
||||||
|
strategy = iron_condor.strategy,
|
||||||
|
entry_time = iron_condor.entry_time
|
||||||
|
)
|
||||||
|
spreads = trade_record['Spreads'].iloc[0]
|
||||||
|
|
||||||
|
spread_index = 0 if option_type == 'C' else 1 # 'C' for call spread, 'P' for put spread.
|
||||||
|
|
||||||
|
spreads[spread_index]['Close'] = close_price
|
||||||
|
spreads[spread_index]['Exit Slippage'] = exit_slippage
|
||||||
|
|
||||||
|
upsert(
|
||||||
|
DataFrame([{
|
||||||
|
'Date': date,
|
||||||
|
'Symbol': iron_condor.symbol,
|
||||||
|
'Strategy': iron_condor.strategy,
|
||||||
|
'Entry Time': iron_condor.entry_time,
|
||||||
|
'Exit Time': None,
|
||||||
|
'Spreads': spreads,
|
||||||
|
'Profit': None # To be updated end of day.
|
||||||
|
}])
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user