def main(serverSite,apikey): stockdata = read_data_daily(apikey,tickers = ["AAPL"]) write_data_to_sql(stockdata, "backtestdata", if_exists = "replace", serverSite = serverSite) #stockdata15min = read_data_alpaca(pd.Series(dowTickers), "15Min") #write_data_to_sql(stockdata, "backtestdata15min", if_exists = "append") #Do stuff with this! crossovers = find_ma_crossovers(server.serverSite)
def portfolio_value_to_db(apis, serverSite, code): #Fetch the current portfolio values and store in db. Code is used to differentiate the apis today = date.today() time = today.strftime("%d/%m/%Y") portvalue = apis.alpacaApi.get_account().portfolio_value df = pd.DataFrame({ "code": [code], "portval": [portvalue], "timestamp": [time] }) db.write_data_to_sql(df, "portvalues", serverSite, if_exists="append")
def active_trades_to_db(active_trades, serverSite, table_name="active_trades"): active_trade_lists = [] for trade in active_trades: tradeinfo = [ trade.ticker, trade.posSize, trade.entryPrice, trade.stopPrice, trade.targetPrice, trade.strategy, trade.unrealPL ] active_trade_lists.append(tradeinfo) colnames = [ "ticker", "PosSize", "EntryPrice", "StopPrice", "TargetPrice", "Strategy", "UnrealPl" ] active_trade_df = pd.DataFrame(active_trade_lists, columns=colnames) db.write_data_to_sql(active_trade_df, table_name, serverSite)
def echo_active_trades_to_db(apis, serverSite): current_portfolio = apis.alpacaApi.list_positions() current_port_list = [] for position in current_portfolio: current_port_list.append([ position.symbol, position.current_price, position.lastday_price, position.qty, position.unrealized_plpc ]) colnames = ["ticker", "current_price", "lastday_price", "qty", "unreal_pl"] current_port_df = pd.DataFrame(current_port_list, columns=colnames) db.write_data_to_sql(current_port_df, "active_trades_echo", serverSite, if_exists="replace")
def get_watchlist_price(watchlist_df, wl_code, apis, server): watchlist_bars = apis.alpacaApi.get_barset(watchlist_df.ticker, 'minute', limit=1).df #The API that returns real time data is not perfect in my opinion. #It returns the last minute candle that the given tickes has traded, not neccecarliy the latest #This has led me to do this wierd contraption where i fill the df's all NANs with the mean, and then I can just transpose it and take the first column #Since all the rows contain the same values after the fill.na with mean. #You can set the start and end dates on the API call but I'm not sure if it supports minutes, since that is what I would be interested in. #This should not have been a problem but it it was watchlist_bars = watchlist_bars.fillna(watchlist_bars.mean()) #We only want the "close" values, this is the first way I could come up with. Surely there is better. close_columns = [col for col in watchlist_bars.columns if "close" in col] close_values = watchlist_bars[close_columns].transpose().iloc[:, 0] close_values.sort_index() watchlist_df["current_price"] = list(close_values) watchlist_df["price_difference"] = watchlist_df["price"] - watchlist_df[ "current_price"] #Update the db prices db.write_data_to_sql(pd.DataFrame(watchlist_df), wl_code + "_watchlist", server.serverSite) found_trades_long = [] found_trades_short = [] longs = watchlist_df[watchlist_df["side"].str.match("buy")] shorts = watchlist_df[watchlist_df["side"].str.match("sell")] for index, stock in longs.iterrows(): if (stock["price_difference"] < 0): found_trades_long.append(stock["ticker"]) for index, stock in shorts.iterrows(): if (stock["price_difference"] > 0): found_trades_short.append(stock["ticker"]) return found_trades_long, found_trades_short
def updateTradeDb(self, action, initiated, apis, server, algo="charlie"): now = str(apis.alpacaApi.get_clock().timestamp)[0:19] #Different update depending on if the order was initiated of flattend. if (initiated == False): dfData = { "Timestamp": [now], "Ticker": [self.ticker], "Size": [self.posSize], "Side": [self.orderSide], "Strategy": [self.strategy], "Action": [action], "Result": [self.unrealPL] } if (initiated): dfData = { "Timestamp": [now], "Ticker": [self.ticker], "Size": [self.posSize], "Side": [self.orderSide], "Strategy": [self.strategy], "Action": [action], "Result": ["init"] } tradedb = pd.DataFrame(data=dfData) if algo == "charlie": db.write_data_to_sql(tradedb, "tradehistory", if_exists="append", serverSite=server.serverSite) elif algo == "delta": db.write_data_to_sql(tradedb, "tradehistory_delta", if_exists="append", serverSite=server.serverSite) elif algo == "echo": db.write_data_to_sql(tradedb, "tradehistory_echo", if_exists="append", serverSite=server.serverSite)
def run_charlie(server, apis, active_trades, ema_time_period, maxPosSize, maxPosValue, now): #Get the active trade last 15min bars func.current_active_trade_prices(active_trades, apis) #Check if the bar has closed below stoploss -> flatten trade active_trades = func.check_stoploss(active_trades, ema_time_period, server, apis) #Check if bar high is above target -> flatten trade. active_trades = func.check_target(active_trades, apis, server) #The idea behind this is that i can remotely add or remove trades from the database, and they would get updated here too. #Read watchlists ma_watchlist = db.read_from_database("SELECT * from ma_watchlist", server.serverSite) hd_watchlist = db.read_from_database("SELECT * from hd_watchlist", server.serverSite) bb_watchlist = db.read_from_database("SELECT * from bb_watchlist", server.serverSite) #Loop trough watchlist and check if the value has been crossed and fire trades. if (len(ma_watchlist) > 0): found_trades_long_ma, found_trades_short_ma = func.get_watchlist_price( ma_watchlist, "ma", apis, server) succ_trades_long_ma = func.fire_orders(found_trades_long_ma, "buy", str(now), "20EMA", apis, server, maxPosSize, maxPosValue) succ_trades_short_ma = func.fire_orders(found_trades_short_ma, "sell", str(now), "20EMA", apis, server, maxPosSize, maxPosValue) else: #If watchlist is empty, just create empty lists. found_trades_long_ma = [] found_trades_short_ma = [] succ_trades_long_ma = [] succ_trades_short_ma = [] if (len(hd_watchlist) > 0): found_trades_long_hd, found_trades_short_hd = func.get_watchlist_price( hd_watchlist, "hd", apis, server) #No short strades for the HD strategy should appear succ_trades_long_hd = func.fire_orders(found_trades_long_hd, "buy", str(now), "H/D", apis, server, maxPosSize, maxPosValue) else: #If watchlist is empty, just create empty lists. found_trades_long_hd = [] succ_trades_long_hd = [] #Loop trough watchlist and check if the value has been crossed and fire trades. if (len(bb_watchlist) > 0): found_trades_long_bb, found_trades_short_bb = func.get_watchlist_price( bb_watchlist, "bb", apis, server) succ_trades_long_bb = func.fire_orders(found_trades_long_bb, "buy", str(now), "BB", apis, server, maxPosSize, maxPosValue) succ_trades_short_bb = func.fire_orders(found_trades_short_bb, "sell", str(now), "BB", apis, server, maxPosSize, maxPosValue) else: #If watchlist is empty, just create empty lists. found_trades_long_bb = [] found_trades_short_bb = [] succ_trades_long_bb = [] succ_trades_short_bb = [] #Append succesfull trades to the active trades if (len(succ_trades_long_ma + succ_trades_short_ma + succ_trades_long_hd + succ_trades_long_bb + succ_trades_short_bb) > 0): for succ_trade in succ_trades_long_ma + succ_trades_short_ma + succ_trades_long_hd + succ_trades_long_bb + succ_trades_short_bb: active_trades.append(succ_trade) traded_stocks = found_trades_long_ma + found_trades_short_ma + found_trades_long_hd + found_trades_short_bb + found_trades_long_bb #Delete trades from watchlist if (len(traded_stocks) > 0): ma_watchlist = ma_watchlist[~ma_watchlist.ticker.str. contains('|'.join(traded_stocks))] hd_watchlist = hd_watchlist[~hd_watchlist.ticker.str. contains('|'.join(traded_stocks))] bb_watchlist = bb_watchlist[~bb_watchlist.ticker.str. contains('|'.join(traded_stocks))] #Update the db watchlist db.write_data_to_sql(pd.DataFrame(ma_watchlist), "ma_watchlist", server.serverSite) db.write_data_to_sql(pd.DataFrame(hd_watchlist), "hd_watchlist", server.serverSite) db.write_data_to_sql(pd.DataFrame(bb_watchlist), "bb_watchlist", server.serverSite) #update trades in db func.active_trades_to_db(active_trades, server.serverSite)
def get_watchlist_price_broken(watchlist_df, wl_code, apis, server): #Working around the limitations of the API, one call can only contain 100 tickers sumtickers = watchlist_df.shape[0] index = 100 #These lists will be populated and returned found_trades_long = [] found_trades_short = [] while True: watchlist_df_sliced = watchlist_df.iloc[index - 100:index, :] watchlist_bars = apis.alpacaApi.get_barset( watchlist_df.ticker[index - 100:index], 'minute', limit=1).df #The API that returns real time data is not perfect in my opinion. #It returns the last minute candle that the given tickes has traded, not neccecarliy the latest #This has led me to do this wierd contraption where i fill the df's all NANs with the mean, and then I can just transpose it and take the first column #Since all the rows contain the same values after the fill.na with mean. #You can set the start and end dates on the API call but I'm not sure if it supports minutes, since that is what I would be interested in. #This should not have been a problem but it it was watchlist_bars = watchlist_bars.fillna(watchlist_bars.mean()) #We only want the "close" values, this is the first way I could come up with. Surely there are better ways. close_columns = [ col for col in watchlist_bars.columns if "close" in col ] close_values = watchlist_bars[close_columns].transpose().iloc[:, 0] close_values.sort_index() watchlist_df_sliced.insert(4, "current_price", list(close_values), True) price_difference = watchlist_df_sliced["price"] - watchlist_df_sliced[ "current_price"] watchlist_df_sliced.insert(5, "price_difference", list(price_difference), True) #Update the db prices #If the tickers are more than 100, we are going to append items to the watchlist db and not replace. fate = "replace" if sumtickers > index: fate = "append" db.write_data_to_sql(watchlist_df_sliced, wl_code + "_watchlist", server.serverSite, fate) longs = watchlist_df_sliced[watchlist_df_sliced["side"].str.match( "buy")] for element, stock in longs.iterrows(): if (stock["price_difference"] < 0): found_trades_long.append(stock["ticker"]) shorts = watchlist_df_sliced[watchlist_df_sliced["side"].str.match( "sell")] for element, stock in shorts.iterrows(): if (stock["price_difference"] > 0): found_trades_short.append(stock["ticker"]) #If the number of symbols were less than 100, we break here. If not we will loop again and check again. if index > sumtickers: break index = index + 100 return found_trades_long, found_trades_short
def main(apis, server, startup, startupPrevious, watchlists, maxPosSize, maxPosValue, apis_delta, apis_echo, ema_time_period): logging.basicConfig(filename = "logs.log", level=logging.DEBUG) #Creating the database and putting the data for the last month as a base. if (startup): logging.info("Startup is true, populating the database with stockdata.") db_main(server, apis,timeframe = "3m") #Adding the previous data to the database at startup. if (startupPrevious): logging.info("StartupPrevious is true, populating the database with previous days stockdata.") db_main(server, apis,timeframe = "previous") #Look for currently active charlie trades, make trade objects and append to active trades. active_trades = get_active_trades(apis) logging.info("Start complete Charlie") #Look for currently active delta trades, make trade objects and append to active trades. active_trades_delta = get_active_trades(apis_delta) logging.info("Start complete Delta") while True: #I have had instaces when the API has been unreachable. try: clock = apis.alpacaApi.get_clock() now = str(clock.timestamp)[0:19] #Get only current date and time. Only returns YYYY-MM-DD-HH:MM. The and seconds are parsed except: logging.error("Could not fetch clock") #Create charlie watchlist and rewrite db before market opens. if ((not clock.is_open and "09:05" in now) or watchlists): latest_data_from_db = db.read_from_database("SELECT date FROM dailydata ORDER BY date DESC limit 1;", server.serverSite).iloc[0,0] latest_data_from_api = db.get_iex_data(["AAPL"],timeframe = "previous", apikey = apis.iexKey).iloc[0,0] #Testing what the latest data for aapl is, any ticker will do. #If there is new data, which is true every day except weekends and if the market was closed -> fetch previous days data. if latest_data_from_db != latest_data_from_api: #Fetch more data logging.info("updating databse with latest data") db_main(server, apis, timeframe = "previous") logging.info("Database ready") #Create the watchlist logging.info("Building watchlist") col_lables = ["ticker","side","price","strategy"] logging.info("Ma watchlist ->") ma_watchlist = pd.DataFrame(strategies.ma_crossover("EMA", ema_time_period, server),columns = col_lables).sort_values("ticker") logging.info("Hd watchlist ->") hd_watchlist = pd.DataFrame(strategies.hammer_doji(server),columns = col_lables).sort_values("ticker") logging.info("BB watchlist ->") bb_watchlist = pd.DataFrame(strategies.bb_cross(server),columns = col_lables).sort_values("ticker") db.write_data_to_sql(pd.DataFrame(ma_watchlist),"ma_watchlist", server.serverSite) #Replace is default, meaning yesterdays watchlist gets deleted. db.write_data_to_sql(pd.DataFrame(hd_watchlist),"hd_watchlist", server.serverSite) db.write_data_to_sql(pd.DataFrame(bb_watchlist),"bb_watchlist", server.serverSite) logging.info("Week52 watchlist ->") week_watchlist = pd.DataFrame(strategies.week_cross(server, apis_delta, active_trades_delta),columns = col_lables).sort_values("ticker") db.write_data_to_sql(pd.DataFrame(week_watchlist),"week_watchlist", server.serverSite) logging.info("Watchlists ready") try: clock = apis.alpacaApi.get_clock() now = str(clock.timestamp)[0:19] #Get only current date an time. except: logging.error("Could not fetch clock") if (clock.is_open): #Check if market is open logging.info("Market open!") time.sleep(900) #Sleep for the first 15 min to avoid the larget market volatility #Fetch portfolio values to db func.portfolio_value_to_db(apis, server.serverSite, "Charlie") func.portfolio_value_to_db(apis_delta, server.serverSite, "Delta") func.portfolio_value_to_db(apis_echo, server.serverSite,"Echo") #Echo should be only run once a day so running if at the start of the day. echo.run_echo(server,apis_echo,now) while apis.alpacaApi.get_clock().is_open: try: clock = apis.alpacaApi.get_clock() now = str(clock.timestamp)[0:19] #Get only current date an time. except: logging.error("Could not fetch clock") #Running charlie charlie.run_charlie(server, apis, active_trades, ema_time_period, maxPosSize, maxPosValue, now) #Running delta delta.run_delta(server, apis_delta, active_trades_delta,ema_time_period, maxPosSize,maxPosValue, now) #Add more algos here time.sleep(sleepBetweenCalls) time.sleep(sleepBetweenCalls*3) #Print out that the system is still running. if ("00" in now): logging.info("System is running", now)