2023-12-07 16:12:50 +00:00
|
|
|
import schedule
|
|
|
|
import time
|
|
|
|
|
2024-01-19 21:19:13 +00:00
|
|
|
from database.backtest import backtest_results
|
|
|
|
from datetime import datetime, timedelta
|
2023-12-13 14:39:58 +00:00
|
|
|
from dotenv import load_dotenv
|
|
|
|
from ibkr import Client
|
2023-12-07 16:12:50 +00:00
|
|
|
from iron_condor import enter_iron_condor
|
|
|
|
from multiprocessing import Process
|
2023-12-13 14:39:58 +00:00
|
|
|
from os import getenv
|
2024-01-29 16:39:58 +00:00
|
|
|
from pytz import timezone
|
2023-12-13 14:39:58 +00:00
|
|
|
|
|
|
|
load_dotenv()
|
2023-12-07 16:12:50 +00:00
|
|
|
|
2024-01-19 21:19:13 +00:00
|
|
|
entry_time_format = '%H:%M:%S'
|
2024-01-29 16:39:58 +00:00
|
|
|
eastern_timezone = 'America/New_York'
|
2024-01-19 21:19:13 +00:00
|
|
|
|
|
|
|
def available_entry_times():
|
|
|
|
start = datetime.strptime('09:35:00', entry_time_format)
|
|
|
|
end = datetime.strptime('15:55:00', entry_time_format)
|
|
|
|
|
|
|
|
current_time = start
|
|
|
|
entry_times = []
|
|
|
|
|
|
|
|
while current_time <= end:
|
|
|
|
entry_times.append(current_time.strftime(entry_time_format))
|
|
|
|
current_time += timedelta(minutes = 5)
|
|
|
|
|
|
|
|
return entry_times
|
|
|
|
|
|
|
|
def best_entry_times():
|
|
|
|
end_date = datetime.now().replace(hour = 0, minute = 0, second = 0, microsecond = 0)
|
|
|
|
start_date = end_date - timedelta(days = 10) # TODO: Really want 5 most recent trading days.
|
|
|
|
|
|
|
|
cumulative_profits = {}
|
|
|
|
for entry_time in available_entry_times():
|
|
|
|
backtest = backtest_results('SPX', f'10 Delta Iron Condor @ {entry_time}',
|
|
|
|
start_date = start_date, end_date = end_date)
|
|
|
|
cumulative_profits[entry_time] = backtest.tail(5)['Profit'].sum()
|
|
|
|
print(backtest)
|
|
|
|
|
|
|
|
sorted_entry_times = sorted(cumulative_profits.items(), key=lambda x: x[1], reverse=True)[:10]
|
|
|
|
return [entry_time for entry_time, _ in sorted_entry_times]
|
2023-12-07 16:12:50 +00:00
|
|
|
|
|
|
|
def enter_trade():
|
|
|
|
job_process = Process(target = enter_iron_condor)
|
|
|
|
job_process.start()
|
|
|
|
|
2023-12-13 14:39:58 +00:00
|
|
|
def connection_successful():
|
|
|
|
try:
|
|
|
|
ibkr_host = getenv('IBKR_HOST')
|
|
|
|
ibkr_port = getenv('IBKR_PORT')
|
|
|
|
Client(host = ibkr_host, port = ibkr_port)
|
|
|
|
return True
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
|
2023-12-07 16:12:50 +00:00
|
|
|
if __name__ == '__main__':
|
2023-12-13 14:39:58 +00:00
|
|
|
if connection_successful():
|
|
|
|
print('Connected to IBKR.')
|
|
|
|
|
2024-01-29 16:39:58 +00:00
|
|
|
now = datetime.now(timezone(eastern_timezone))
|
|
|
|
|
2024-01-29 16:44:37 +00:00
|
|
|
entry_times = sorted(best_entry_times())
|
2024-01-19 21:19:13 +00:00
|
|
|
print(entry_times)
|
2023-12-13 14:39:58 +00:00
|
|
|
for entry_time in entry_times:
|
2024-01-29 16:39:58 +00:00
|
|
|
schedule_time = datetime.strptime(entry_time, '%H:%M:%S').replace(
|
|
|
|
year = now.year,
|
|
|
|
month = now.month,
|
|
|
|
day = now.day,
|
|
|
|
tzinfo = now.tzinfo
|
|
|
|
)
|
|
|
|
|
|
|
|
# Prevent scheduling for times that have already elapsed.
|
|
|
|
if schedule_time > now:
|
|
|
|
print(f'Scheduling for {entry_time}.')
|
|
|
|
schedule.every().day.at(entry_time, eastern_timezone).do(enter_trade)
|
2023-12-07 16:12:50 +00:00
|
|
|
|
2023-12-13 14:39:58 +00:00
|
|
|
while True:
|
|
|
|
schedule.run_pending()
|
|
|
|
time.sleep(1)
|
|
|
|
else:
|
|
|
|
print('ERROR: Cannot connect to IBKR. Ensure that TWS / Gateway is running.')
|