Skip to content

Commit

Permalink
update to 3.12
Browse files Browse the repository at this point in the history
  • Loading branch information
letianzj committed Jun 14, 2024
1 parent eab8a3c commit 1dd44b6
Show file tree
Hide file tree
Showing 54 changed files with 638 additions and 588 deletions.
6 changes: 4 additions & 2 deletions examples/buy_and_hold_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

import os
from datetime import datetime

import pytz
from quanttrader.util.util_func import read_ohlcv_csv
from quanttrader.strategy.strategy_base import StrategyBase

from quanttrader.backtest_engine import BacktestEngine
from quanttrader.data.tick_event import TickEvent
from quanttrader.strategy.strategy_base import StrategyBase
from quanttrader.util.util_func import read_ohlcv_csv


class BuyAndHoldStrategy(StrategyBase):
Expand Down
216 changes: 110 additions & 106 deletions examples/download_historical_data_from_ib.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,123 +5,126 @@
Making six or more historical data requests for the same Contract, Exchange and Tick Type within two seconds.
Making more than 60 requests within any ten minute period.
"""
import os
import argparse
import pickle
import time
from datetime import datetime, timedelta
from signal import SIG_DFL, SIGINT, signal

import pandas as pd
import numpy as np
from signal import signal, SIGINT, SIG_DFL
import pickle
from quanttrader.event.event import EventType
from quanttrader.event.live_event_engine import LiveEventEngine

from quanttrader.brokerage.ib_brokerage import InteractiveBrokers
from quanttrader.data.bar_event import BarEvent
from quanttrader.event.event import EventType, LogEvent
from quanttrader.event.live_event_engine import LiveEventEngine

signal(SIGINT, SIG_DFL)
df = pd.DataFrame(columns=["Open", "High", "Low", "Close", "Volume"])


def log_event_handler(log_event):
print(f"{log_event.timestamp}: {log_event.content}")


def historical_event_handler(bar_event):
class HistoricalDataDownloader:
"""
local timezone based on tws setting
"""
global df
row_dict = {}
row_dict["Open"] = bar_event.open_price
row_dict["High"] = bar_event.high_price
row_dict["Low"] = bar_event.low_price
row_dict["Close"] = bar_event.close_price
row_dict["Volume"] = bar_event.volume
df1 = pd.DataFrame(row_dict, index=[bar_event.bar_start_time])
df = pd.concat([df, df1], axis=0)


def run(args):
global df
dfd = pd.DataFrame()
dict_all = dict()
events_engine = LiveEventEngine()
tick_event_engine = LiveEventEngine()
broker = InteractiveBrokers(events_engine, tick_event_engine, "DU0001")
broker.reqid = 5000
events_engine.register_handler(EventType.LOG, log_event_handler)
tick_event_engine.register_handler(EventType.BAR, historical_event_handler)
events_engine.start()
tick_event_engine.start()

broker.connect("127.0.0.1", 7497, 0)
time.sleep(5) # 5 seconds

# RTH stock 9:30~16:00; FUT 9:30~17:00, ES halt 16:15~16:30
# 7.5h x 2 = 15 requests = 15*15 ~ 4min
symbols = [
"ESU0 FUT GLOBEX", # 9:30 a.m. ET on the 3rd Friday of the contract month; 15:14:30 – 15:15:00 CT; final 9:30am opening prices
# 'NQU0 FUT GLOBEX', # 9:30 a.m. ET on the 3rd Friday of the contract month
# 'CLU0 FUT NYNEX', # 3 business day prior to the 25th calendar day of the month prior to the contract month, if not business day; active -2D; 4:28:00 to 14:30:00 ET; 14:00:00 and 14:30:00 ET
# 'CLV0 FUT NYNEX',
# 'HOU0 FUT NYMEX', # last business day of the month prior to the contract month; active -2D CL; 14:28:00 to 14:30:00 ET, 14:00:00 and 14:30:00 ET.
# 'HOV0 FUT NYMEX',
# 'RBU0 FUT NYMEX', # last business day of the month prior to the contract month.; active -2D CL; 14:28:00 to 14:30:00 ET, 14:00:00 and 14:30:00 ET.
# 'RBV0 FUT NYMEX',
# 'NGU0 FUT NYMEX', # 3rd last business days of the month prior to the contract month; active -2D. 14:28:00 to 14:30:00 ET; 14:00:00 and 14:30:00 ET
# 'NGV0 FUT NYMEX',
# # 'SPY STK SMART',
# 'QQQ STK SMART',
# 'XLE STK SMART',
# 'XLF STK SMART',
# 'XLU STK SMART',
# 'XLK STK SMART',
# 'XLP STK SMART',
# 'XLI STK SMART',
# 'XLV STK SMART',
# 'XLB STK SMART',
# 'XLY STK SMART',
# 'XLRE STK SMART',
# 'XLC STK SMART'
]
date = args.date
path = args.path

for sym in symbols:
end_date = datetime.strptime(date, "%Y%m%d")
if "STK" in sym:
end_date = end_date + timedelta(hours=16) # 16:00
else: # FUT
end_date = end_date + timedelta(hours=17) # 17:00

while end_date.hour >= 10: # last one is (9:30am, 10am)
print(sym, end_date)
broker.request_historical_data(sym, end_date)
end_date = end_date - timedelta(minutes=30)
time.sleep(15) # 15 seconds

# daily combine and remove duplicates
dfd = df.combine_first(dfd)
# ready for the next 30min
df = pd.DataFrame(columns=["Open", "High", "Low", "Close", "Volume"])

dfd.sort_index(inplace=True)
dict_all[sym] = dfd

dict_stats = {}
for k, v in dict_all.items():
dict_stats[k] = v.shape[0]

df_stats = pd.DataFrame.from_dict(dict_stats, orient="index")
print("-----------------------------------------------")
print(df_stats)

outfile = f"{path}{date}.pkl"
with open(outfile, "wb") as f:
pickle.dump(dict_all, f, pickle.HIGHEST_PROTOCOL)

broker.disconnect()
events_engine.stop()
tick_event_engine.stop()

def __init__(self, date: str, path: str) -> None:
self.date = date
self.path = path
self.df = pd.DataFrame(columns=["Open", "High", "Low", "Close", "Volume"])

def log_event_handler(self, log_event: LogEvent) -> None:
print(f"{log_event.timestamp}: {log_event.content}")

def historical_event_handler(self, bar_event: BarEvent) -> None:
row_dict = {}
row_dict["Open"] = bar_event.open_price
row_dict["High"] = bar_event.high_price
row_dict["Low"] = bar_event.low_price
row_dict["Close"] = bar_event.close_price
row_dict["Volume"] = bar_event.volume
df1 = pd.DataFrame(row_dict, index=[bar_event.bar_start_time])
self.df = pd.concat([self.df, df1], axis=0)

def run(self) -> None:
dfd = pd.DataFrame()
dict_all = dict()
events_engine = LiveEventEngine()
tick_event_engine = LiveEventEngine()
broker = InteractiveBrokers(events_engine, tick_event_engine, "DU0001")
broker.reqid = 5000
events_engine.register_handler(EventType.LOG, self.log_event_handler)
tick_event_engine.register_handler(EventType.BAR, self.historical_event_handler)
events_engine.start()
tick_event_engine.start()

broker.connect("127.0.0.1", 7497, 0)
time.sleep(5) # 5 seconds

# RTH stock 9:30~16:00; FUT 9:30~17:00, ES halt 16:15~16:30
# 7.5h x 2 = 15 requests = 15*15 ~ 4min
symbols = [
"ESU0 FUT GLOBEX", # 9:30 a.m. ET on the 3rd Friday of the contract month; 15:14:30 – 15:15:00 CT; final 9:30am opening prices
# 'NQU0 FUT GLOBEX', # 9:30 a.m. ET on the 3rd Friday of the contract month
# 'CLU0 FUT NYNEX', # 3 business day prior to the 25th calendar day of the month prior to the contract month, if not business day; active -2D; 4:28:00 to 14:30:00 ET; 14:00:00 and 14:30:00 ET
# 'CLV0 FUT NYNEX',
# 'HOU0 FUT NYMEX', # last business day of the month prior to the contract month; active -2D CL; 14:28:00 to 14:30:00 ET, 14:00:00 and 14:30:00 ET.
# 'HOV0 FUT NYMEX',
# 'RBU0 FUT NYMEX', # last business day of the month prior to the contract month.; active -2D CL; 14:28:00 to 14:30:00 ET, 14:00:00 and 14:30:00 ET.
# 'RBV0 FUT NYMEX',
# 'NGU0 FUT NYMEX', # 3rd last business days of the month prior to the contract month; active -2D. 14:28:00 to 14:30:00 ET; 14:00:00 and 14:30:00 ET
# 'NGV0 FUT NYMEX',
# # 'SPY STK SMART',
# 'QQQ STK SMART',
# 'XLE STK SMART',
# 'XLF STK SMART',
# 'XLU STK SMART',
# 'XLK STK SMART',
# 'XLP STK SMART',
# 'XLI STK SMART',
# 'XLV STK SMART',
# 'XLB STK SMART',
# 'XLY STK SMART',
# 'XLRE STK SMART',
# 'XLC STK SMART'
]

for sym in symbols:
end_date = datetime.strptime(self.date, "%Y%m%d")
if "STK" in sym:
end_date = end_date + timedelta(hours=16) # 16:00
else: # FUT
end_date = end_date + timedelta(hours=17) # 17:00

while end_date.hour >= 10: # last one is (9:30am, 10am)
print(sym, end_date)
broker.request_historical_data(sym, end_date)
end_date = end_date - timedelta(minutes=30)
time.sleep(15) # 15 seconds

# daily combine and remove duplicates
dfd = self.df.combine_first(dfd)
# ready for the next 30min
self.df = pd.DataFrame(
columns=["Open", "High", "Low", "Close", "Volume"]
)

dfd.sort_index(inplace=True)
dict_all[sym] = dfd

dict_stats = {}
for k, v in dict_all.items():
dict_stats[k] = v.shape[0]

df_stats = pd.DataFrame.from_dict(dict_stats, orient="index")
print("-----------------------------------------------")
print(df_stats)

outfile = f"{self.path}{self.date}.pkl"
with open(outfile, "wb") as f:
pickle.dump(dict_all, f, pickle.HIGHEST_PROTOCOL)

broker.disconnect()
events_engine.stop()
tick_event_engine.stop()


if __name__ == "__main__":
Expand All @@ -134,4 +137,5 @@ def run(args):
)

args = parser.parse_args()
run(args)
hdd = HistoricalDataDownloader(date=args.date, path=args.path)
hdd.run()
19 changes: 8 additions & 11 deletions examples/download_ib_contract_info.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import argparse
import logging
import time
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
from signal import SIG_DFL, SIGINT, signal

from ibapi.contract import Contract
from signal import signal, SIGINT, SIG_DFL
import logging
from quanttrader.event.event import EventType
from quanttrader.event.live_event_engine import LiveEventEngine

from quanttrader.brokerage.ib_brokerage import InteractiveBrokers
from quanttrader.event.live_event_engine import LiveEventEngine

signal(SIGINT, SIG_DFL)

Expand All @@ -20,7 +17,7 @@ def log_event_handler(log_event):
print(f"{log_event.timestamp}: {log_event.content}")


def run(args):
def run(conid):
_logger = logging.getLogger("quanttrader")
_logger.setLevel(logging.DEBUG)
handler1 = logging.StreamHandler()
Expand All @@ -42,7 +39,7 @@ def run(args):
time.sleep(5) # 5 seconds

contract = Contract()
contract.conId = args.conid
contract.conId = conid

broker.api.reqContractDetails(broker.reqid, contract)

Expand All @@ -56,4 +53,4 @@ def run(args):
parser.add_argument("--conid", help="conid e.g. 383974324", required=True)

args = parser.parse_args()
run(args)
run(args.conid)
36 changes: 18 additions & 18 deletions examples/live_engine.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import argparse
import importlib
import logging
import os
import sys
from datetime import datetime
from signal import SIG_DFL, SIGINT, signal

import qdarkstyle
import yaml
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5 import QtGui, QtWidgets

from quanttrader.gui.ui_main_window import MainWindow
import atexit
from signal import signal, SIGINT, SIG_DFL
from os import kill
from multiprocessing import Process
import logging

# https://stackoverflow.com/questions/4938723/what-is-the-correct-way-to-make-my-pyqt-application-quit-when-killed-from-the-co
signal(SIGINT, SIG_DFL)
Expand Down Expand Up @@ -72,32 +72,32 @@ def main(config_file, instrument_meta_file):
if "strategy" in name and ".pyc" not in name:
s = name.replace(".py", "")
try:
moduleName = f"strategy.{s}"
module_name = f"strategy.{s}"
# import module
module = importlib.import_module(moduleName)
module = importlib.import_module(module_name)
for k in dir(module):
if (
("Strategy" in k)
and ("Abstract" not in k)
and (k in config["strategy"])
):
v = module.__getattribute__(k)
v = getattr(module, k)
_strategy = v()
_strategy.set_name(k)
strategy_dict[k] = _strategy
except Exception as e:
except Exception as e: # pylint: disable=broad-except
_logger2.error(f"Unable to load strategy {s}: {str(e)}")

app = QtWidgets.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon("gui/image/logo.ico"))
mainWindow = MainWindow(config, instrument_meta, strategy_dict)
app = QtWidgets.QApplication(sys.argv) # pylint: disable=c-extension-no-member
app.setWindowIcon(
QtGui.QIcon("gui/image/logo.ico")
) # pylint: disable=c-extension-no-member
main_window = MainWindow(config, instrument_meta, strategy_dict)

if config["theme"] == "dark":
import qdarkstyle

app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())

mainWindow.show() # .showMaximized()
main_window.show() # .showMaximized()
sys.exit(app.exec_())


Expand Down
Loading

0 comments on commit 1dd44b6

Please sign in to comment.