def __init__(self, manager, name, symbols, properties, required=[], mainBarsize=""): self.logger = MyLogger.getLogger(name, file=f"{name}.log", level=logging.INFO) self.clock = TradingClock.getInstance() self.manager: Manager = manager self.name = name self.id = uuid.uuid1() self.clock = TradingClock.getInstance() self.symbols = symbols self.mainBarsize = mainBarsize # Check properties self.__dict__ = {**self.__dict__, **properties} assert \ all([rp in self.__dict__.keys() and self.__dict__[rp] is not None for rp in required]), \ f"Missing required properties {[rp for rp in required if (rp not in self.__dict__.keys()) or (self.__dict__[rp] is None)]}" self.__symbols = {} # map symbol to datas self.__requests = {} # map requests to symbol self.indicators = {} # Call abstract setup method self.setup()
def __init__(self, parent, simtracker, account, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.logger = MyLogger.getLogger('StratView') self.simtracker = simtracker self.account = account self.canvas = None self.legend = tk.Frame(self) self.legend.pack(side=tk.RIGHT)
def __init__(self, endpoint): self.logger = MyLogger.getLogger('TestApp', file='trades.log', level=MyLogger.TRADE) self.clock = TradingClock.getInstance() self.datafactory = DataFactory.getInstance() self.endpoint = endpoint self.clock.add_callback(self.time_change) self.pending_orders = {} self.historical_subscribers = {}
def __init__(self, startingcapital): self.logger = MyLogger.getLogger("ACC") self.datafactory = DataFactory.getInstance() self.clock = TradingClock.getInstance() self.clock.add_callback(self.time_change) self.orderLedger = {} self.portfolio = {} # Portfolio(startingcapital) self.cash = startingcapital self.CASH = pd.Series() self.HOLDINGS = pd.Series() self.done = False
def __init__(self, simtracker, account, strategies, rapid=False, times=None, setup_days=3, barsize="5 min"): threading.Thread.__init__(self) self.simtracker = simtracker self.account = account self.logger = MyLogger.getLogger('main') self.strategies = strategies self.symbols = functools.reduce(lambda a, b: set(a + b), [skwa["symbols"] for s, skwa in strategies]) self.barsize = barsize self.rapid = rapid self.setup_days = setup_days if times is None: self.times = [ datetime.time(10, 30), datetime.time(11, 30), datetime.time(12, 30), datetime.time(13, 30), datetime.time(14, 30), datetime.time(15, 30), ] else: self.times = times
def replace_empties(data, goal=None): logger = MyLogger.getLogger("RepUtil") if goal is not None and goal < data.index[-1]: logger.warn(f"Goal date {goal} is pre-data end {data.index[-1]}, resetting") goal = data.index[-1] dates = sorted(list(set(pd.Series(data.index).transform(lambda x: x.date())))) date = dates[0] end_date = dates[-1] if goal is None else goal.date() period = min([abs(d1 - d2) for d1, d2 in zip(data.index[1:], data.index[:-1])]) while date <= end_date: if tcal.is_partial_trading_day(date) or tcal.is_trading_day(date): #TODO: Bug - min period changed if get a partial bar if period > datetime.timedelta(minutes=5): # TODO: Bit ugly.... shoed in missing_ranges = [] if date not in dates: missing_ranges = [[data.index[0].replace(year=date.year, month=date.month, day=date.day)]] else: ttimes = tcal.tradingtimes(date) if goal is None: missing_times = ttimes[~ttimes.isin(data.index)] else: missing_times = ttimes[~ttimes.isin(data.index) & (ttimes <= goal)] missing_ranges = [] if len(missing_times): # Blocks of missing data missing_ranges.append([missing_times[0]]) for missing_time in missing_times[1:]: previous = missing_ranges[-1][-1] next_span = missing_time - previous if next_span != period: missing_ranges.append([missing_time]) else: missing_ranges[-1].append(missing_time) # chuck repeated in there for missing_range in missing_ranges: try: before = data[data.index < missing_range[0]] after = data[data.index > missing_range[-1]] previous = before.iloc[-1] patch = pd.DataFrame({"Open": previous.Close, "High": previous.Close, "Low": previous.Close, "Close": previous.Close, "Adj Close": previous.Close, "Volume": 0}, index=missing_range) data = pd.concat([before, patch, after]) data = data[~data.index.duplicated(keep='last')] except Exception as e: print(f"Repair failed for {e}") date += datetime.timedelta(days=1) return data
from Services.SimViewer import SimViewer import pandas as pd from Strategies.Breakouts import Breakouts from Strategies.Crossover import Crossover from Strategies.Crystal import CrystalV3 from Strategies.MACD import MACD from Strategies.RocketCatcher import RocketCatcher from Strategies.Testing import TestStrategy from _config import TICKERS_LEDGER, ASX_GAME import datetime from enum import Enum MyLogger.configure(level=20) import matplotlib.pyplot as plt plt.ioff() if __name__ == "__main__": strategies = Enum('Strategy', 'Test Crystal RocketCatcher Breakouts MACD Crossover') strategy = strategies.Test DataFactory.repaired = True a = Account(5000) st = SimTracker()
def __init__(self): if DataFactory.__instance != None: raise Exception("Singleton") else: self.logger = MyLogger.getLogger("DataFac") DataFactory.__instance = self
def __init__(self, parent, simtracker, account, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.simtracker = simtracker self.account = account self.logger = MyLogger.getLogger("PView") tk.Button(self, text="Refresh", command=self.refresh, relief=tk.GROOVE, borderwidth=1) \ .pack(side=tk.BOTTOM, expand=True, fill=tk.X) tk.Label(self, text="Orders").pack() self.orders_entry = tk.Entry(self) self.orders_entry.pack() self.orders_entry.bind('<Return>', self.refresh) self.orderstv_frame = tk.Frame(self) self.orderstv = ttk.Treeview(self.orderstv_frame) self.orderstv["columns"] = [ "id", "Symbol", "Action", "Time", "Price", "Filled" ] self.orderstv["show"] = "headings" self.orderstv.heading("id", text="") self.orderstv.heading("Symbol", text="Symb") self.orderstv.heading("Action", text="Action") self.orderstv.heading("Time", text="Time") self.orderstv.heading("Price", text="Price") self.orderstv.heading("Filled", text="Filled") col_width = self.orderstv.winfo_width() // len( self.orderstv['columns']) for col in self.orderstv['columns']: self.orderstv.heading(col, anchor=tk.CENTER) self.orderstv.column(col, anchor=tk.CENTER, width=col_width) # set column width self.orderstv.pack(fill=tk.BOTH, expand=True) self.orderstv_frame.pack(fill=tk.BOTH, expand=True) # treeScroll = ttk.Scrollbar(self.orderstv) # treeScroll.configure(command=self.orderstv.yview) # self.orderstv.configure(yscrollcommand=treeScroll.set) tk.Label(self, text="Portfolio").pack() self.holdingstv_frame = tk.Frame(self) self.holdingstv = ttk.Treeview(self.holdingstv_frame) self.holdingstv["columns"] = [ "Symbol", "Vol", "Avg Price", "Price", "Change", "Realised" ] self.holdingstv["show"] = "headings" self.holdingstv.heading("Symbol", text="Symb") self.holdingstv.heading("Vol", text="Vol") self.holdingstv.heading("Avg Price", text="Avg Price") self.holdingstv.heading("Price", text="Price") self.holdingstv.heading("Change", text="%") self.holdingstv.heading("Realised", text="Realised") col_width = self.holdingstv.winfo_width() // len( self.holdingstv['columns']) for col in self.holdingstv['columns']: self.holdingstv.heading(col, anchor=tk.CENTER) self.holdingstv.column(col, anchor=tk.CENTER, width=col_width) # set column width self.holdingstv.pack(fill=tk.BOTH, expand=True) self.holdingstv_frame.pack(fill=tk.BOTH, expand=True) # ttk.Separator(self, orient=tk.HORIZONTAL).pack(fill=tk.X, expand=1) tk.Label(self, text="Value").pack() self.plot_frame = tk.Frame(self, relief=tk.GROOVE, borderwidth=1) self.f = Figure(figsize=(5, 5), dpi=100) self.a = self.f.add_subplot(111) self.a.grid(True) self.a.xaxis.set_major_formatter(mdates.DateFormatter("%m-%d")) self.a.xaxis.set_minor_formatter(mdates.DateFormatter("%m-%d")) self.a.plot([TradingClock.getInstance().sync_datetime], [self.account.value]) # self.cash, = self.a.plot([TradingClock.getInstance().sync_datetime], [self.account.cash]) # self.holdings, = self.a.plot([TradingClock.getInstance().sync_datetime], [self.account.holdings]) self.canvas = FigureCanvasTkAgg(self.f, self.plot_frame) self.canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) self.plot_frame.pack(fill=tk.BOTH, expand=True)
def snapshot_to_fig(snapshot, account=None, savefile=None): logger = MyLogger.getLogger('SS2Fig') legend_indicators = {} data = snapshot.data def getcolor(ii): colors = ["blue", "green", "red", "cyan", "magenta", "yellow"] return colors[ii % len(colors)] def get_addplot(ii, key, indicator, iargs): if "color" not in iargs: iargs["color"] = getcolor(ii) legend_indicators[key] = iargs["color"] if len(indicator) < len(data): missing_points = len(data) - len(indicator) indicator = pd.concat( [indicator, pd.Series([np.nan] * missing_points)]) logger.warn( f"Missing {missing_points} data points for indicator {key}" ) return fplt.make_addplot(indicator, **iargs) indicator_adps = [ get_addplot(i, key, indicator, iargs) for i, (key, (indicator, iargs)) in enumerate(snapshot.indicators.items()) ] trade_adps = [] symbol = snapshot.contract.symbol period = min( [abs(d1 - d2) for d1, d2 in zip(data.index[1:], data.index[:-1])]) if account is not None: # GET THE BUYS try: buy_times, buy_prices = map( list, zip(*[(order["time"], order["lastFillPrice"]) for id, order in account.orderLedger.items() if order["contract"].symbol == symbol and data.index[0] <= order["time"] <= data.index[-1] and order["order"].action == "BUY"])) if len(buy_times): if period > datetime.timedelta(minutes=5): buy_times = [bt.date() for bt in buy_times] buys = pd.Series([ buy_prices[buy_times.index(t)] if t.date() in buy_times else np.nan for t in data.index ]) else: buys = pd.Series([ buy_prices[buy_times.index(t)] if t in buy_times else np.nan for t in data.index ]) if np.any(~np.isnan(buys)): trade_adps.append( fplt.make_addplot( buys.transform(lambda x: x * 0.9975), scatter=True, marker=r'$\uparrow$', markersize=96, color="green")) except ValueError as e: pass except Exception as e: logger.warn(f"Failed buy markers: {e}") # GET THE SELLS try: sell_times, sell_prices = map( list, zip(*[(order["time"], order["lastFillPrice"]) for id, order in account.orderLedger.items() if order["contract"].symbol == symbol and data.index[0] <= order["time"] <= data.index[-1] and order["order"].action == "SELL"])) if len(sell_times): if period > datetime.timedelta(minutes=5): sell_times = [st.date() for st in sell_times] sells = pd.Series([ sell_prices[sell_times.index(t)] if t.date() in sell_times else np.nan for t in data.index ]) else: sells = pd.Series([ sell_prices[sell_times.index(t)] if t in sell_times else np.nan for t in data.index ]) if np.any(~np.isnan(sells)): trade_adps.append( fplt.make_addplot( sells.transform(lambda x: x * 1.0025), scatter=True, marker=r'$\downarrow$', markersize=96, color="red")) except ValueError as e: pass except Exception as e: logger.warn(f"Failed sell markers: {e}") mc = fplt.make_marketcolors(up='#7DFFB8', down='#FF7979', edge='black', wick='black', volume='in') s = fplt.make_mpf_style(base_mpl_style="seaborn", mavcolors=["lightseagreen", "orange"], facecolor="#F9FBFD", gridcolor="#F2F2F2", gridstyle="--", marketcolors=mc) dates = list(set(pd.Series(data.index).transform(lambda x: x.date()))) plotargs = { "type": 'candle', "style": s, "title": symbol, "ylabel": 'Price ($)', "volume": True, "addplot": indicator_adps + trade_adps, "returnfig": True } if savefile is not None: # if period == datetime.timedelta(days=1): # data.index = pd.DatetimeIndex(pd.Series(data.index).transform(lambda x:x.date()), dtype=datetime.date) plotargs["savefig"] = savefile if type(data.index) != pd.DatetimeIndex: # TODO: shouldn't come here data.index = pd.DatetimeIndex(pd.to_datetime(data.index, utc=True)) logger.warn("ERROR index not datetime") for addplots in [ indicator_adps + trade_adps, indicator_adps, trade_adps, [] ]: try: plotargs["addplot"] = addplots fig, ax = fplt.plot(data, **plotargs) break except: pass #fig, ax = fplt.plot(data, **plotargs) if period <= datetime.timedelta(minutes=5): loc = mticker.MultipleLocator(73) ax[0].xaxis.set_major_locator(loc) else: loc = mticker.MultipleLocator(1) #loc = mticker.MultipleLocator(max(len(data)//20, 1)) ax[0].xaxis.set_major_locator(loc) return fig, ax, legend_indicators
from Services.Datafactory import DataFactory from Services.MyLogger import MyLogger from Services.SimTracker import SimTracker from Services.SimViewer import StrategyView from Services.TradingClock import TradingClock from Strategies.Crystal import CrystalV3 from Strategies.RocketCatcher import RocketCatcher from _config import TICKERS_LEDGER from _devconfig import * import random import pandas as pd if __name__ == "__main__": MyLogger.configure(20) logger = MyLogger.getLogger("MAIN") # services DataFactory.repaired = True DataFactory.live_data = True clock, datafactory = TradingClock.getInstance(), DataFactory.getInstance() # absolute times to check for an update times = [ datetime.time(9, 30), datetime.time(10, 30), datetime.time(11, 30), datetime.time(12, 30), datetime.time(13, 30), datetime.time(14, 30),
from DataScrape.ScrapeReddit import ASX_LISTING from Services.MyLogger import MyLogger from Strategies.Crystal import CrystalV3 from Strategies.RocketCatcher import RocketCatcher from _config import TICKERS_LEDGER MyLogger.configure(level=MyLogger.TRADE) from Components.Account import Account from Services.Datafactory import DataFactory from Components.Process import ThreadedTask import pandas as pd import random if __name__ == "__main__": # TODO: proper portfolio # TODO: data cleaning # TODO: parmas DataFactory.repaired = True logger = MyLogger.getLogger("Optimiser", file="optimiser.log", level=MyLogger.OPTY) def get_random_symbols(k=25): tickers_ledger = pd.read_csv(TICKERS_LEDGER) asx_listings = pd.read_csv(ASX_LISTING) return random.choices([ s for t, s, mc, l in zip(asx_listings.title.values, asx_listings.code.values,
import os import pandas as pd from DataScrape.ScrapeReddit import ASX_LISTING from Datasets.scrape_data import replace_empties from Services.Datafactory import DataFactory from Services.MyLogger import MyLogger from _config import TICKERS_LEDGER, ASX_GAME if __name__ == "__main__": logger = MyLogger.getLogger("repair util", level=20) datafactory = DataFactory.getInstance() asx_game = pd.read_csv(ASX_GAME) to_replace = [s + ".AX" for s in asx_game.Code] print(f"TO REPLACE ({len(to_replace)}):") for i, ticker in enumerate(to_replace): DFS = DataFactory.repaired try: print(f"{ticker} ({i + 1}/{len(to_replace)})") datafactory.repaired = False data = datafactory.loadSymbol(ticker).dropna() repaired_data = replace_empties(data) datafactory.repaired = True repaired_data.to_csv( datafactory.getDataDir("5 min") +