def hammer_doji(server): #The idea is to look at yesterdays candles, find hammes/dragonfly dojis/dojis and then initiate trade if we get a new high. watchlist = [] tickers = db.read_snp_tickers(server.serverSite).Symbol.tolist() for ticker in tickers: try: #Get the latest data only data = db.read_from_database( "Select distinct date, ticker,uOpen, uHigh, uLow, uClose from dailydata where ticker ='" + ticker + "' ORDER BY date DESC limit 1;", server.serverSite) data["dojidf"] = talib.CDLDRAGONFLYDOJI(data.uOpen, data.uHigh, data.uLow, data.uClose) data["hammer"] = talib.CDLHAMMER(data.uOpen, data.uHigh, data.uLow, data.uClose) data["doji"] = talib.CDLDOJI(data.uOpen, data.uHigh, data.uLow, data.uClose) if (int(data.dojidf) == 100 | int(data.hammer) == 100 | int(data.doji) == 100): watchlist.append([ticker, "buy", data.uHigh[0], "H/D"]) logging.info("Hd found", ticker) except: logging.info("Database fetch has failed for ticker", ticker) #Returns an list of lists with ticker, enrty price and strategy return watchlist
def week_cross(server, apis_delta, active_trades_delta): #This function looks for stocks that have made a 52 week high or low and compiles them to a watchlist. #If the stock has closed below of above the 52week mark on the daily, we initiate a trade the next day at a new high/low. watchlist = [] #Latest quotes is fetched in the morning. We compare the 52 week high low from between it and what it is at close. highlowdata = db.read_from_database( "Select ticker, week52High, week52Low from latestquotes;", server.serverSite) highlowdata.week52High = highlowdata.week52High.astype("float64") highlowdata.week52Low = highlowdata.week52Low.astype("float64") symbols = "" for ticker in list(highlowdata.ticker): symbols = symbols + "," + ticker str_tickers = symbols[1:] latestClose = pd.read_csv( "https://cloud.iexapis.com/stable/tops/last?symbols=" + str_tickers + "%2b&format=csv&token=" + apis_delta.iexKey) latestClose.columns = ["ticker", "price", "size", "time", "seq"] #Mergethe dfs. We make sute that the right close goes on the right ticker. highlowdata = pd.merge(highlowdata, latestClose, how='outer', on=["ticker"]) highlowdata["highdiff"] = highlowdata.week52High - highlowdata.price highlowdata["lowdiff"] = highlowdata.week52Low - highlowdata.price for ticker in highlowdata.iterrows(): #Looking for stocks above 52week high if ticker[1].highdiff < 0: watchlist.append( [ticker[1].ticker, "buy", ticker[1].price, "Week"]) logging.info("Found week52 crossings for ", ticker[1].ticker) #Looking for stocks below 52week low if ticker[1].lowdiff > 0: watchlist.append( [ticker[1].ticker, "sell", ticker[1].price, "Week"]) logging.info("Found week52 crossings for ", ticker[1].ticker) #We dont want to add to an existing trade, thus we remove it from watch if we have already initiated a trade on it. if len(watchlist) > 0: trade_tickers = [trade.ticker for trade in active_trades_delta] wl_tickers = [trade[0] for trade in watchlist] for ticker in wl_tickers: if ticker in trade_tickers: wl_tickers.remove(ticker) logging.info("Removed", ticker, "from week watchlist") #Returns an list of lists with ticker, enrty price and strategy return watchlist
def ma_crossover(ma, time_period, server): #This function finds stocks to trade. #More accurately it finds stocks that have closed yesterday closed above/below 20EMA #If they pass here they will go on a watch list that from where the orders will be place if they make a new high. #It is written so that the EMA/SMA and time period can be changed on the fly. watchlist = [] tickers = db.read_snp_tickers(server.serverSite).Symbol.tolist() for ticker in tickers: try: data = db.read_from_database( "Select distinct date, ticker, uHigh, uLow, uClose from dailydata where ticker ='" + ticker + "' ORDER BY date DESC limit " + str(time_period + 100) + ";", server.serverSite) #Talib need the oldest data to be first data = data.iloc[::-1] if (ma == "SMA"): data["SMA" + str(time_period)] = talib.SMA( data.uClose, timeperiod=time_period) elif (ma == "EMA"): data["EMA" + str(time_period)] = talib.EMA( data.uClose, timeperiod=time_period) #data["EMA"+str(time_period)] = data["uClose"].ewm(span=20, adjust = False).mean() # alternative method to count EMA #Has the stock crossed above?Limiting to stocks over 10 USD if (data["EMA" + str(time_period)][0] < data.uClose[0] and data["EMA" + str(time_period)][1] > data.uClose[1] ) and data.uHigh[0] > 10: watchlist.append( [ticker, "buy", data.uHigh[0], str(time_period) + "EMA"]) logging.info("Found crossings for ", ticker) #Has the stock crossed below? Limiting to stocks over 10 USD if (data["EMA" + str(time_period)][0] > data.uClose[0] and data["EMA" + str(time_period)][1] < data.uClose[1] ) and data.uHigh[0] > 10: watchlist.append( [ticker, "sell", data.uLow[0], str(time_period) + "EMA"]) logging.info("Found crossings for ", ticker) except: logging.info("Database fetch has failed for ticker ", ticker) #Returns an list of lists with ticker, enrty price and strategy return watchlist
def rebalance_index_positions(apis, server): #Rebalance index portfolio accoring to some metrics.. Used in echo #I have created an diverse universe of different ETFs that should cover a wide range of markets and commodities. #This is a better way of looking up the data, all at once instead of multiple SQL calls. TODO: update charlies datafetch strategies. today = date.today() #only fetching data that is one year old or newer. last_date = date(today.year - 1, today.month, today.day) #today_date = today.strftime("%Y-%m-%d") string_date = last_date.strftime("%Y-%m-%d") #Get all the data etf_data = db.read_from_database( "Select distinct date, ticker, uHigh, uLow, uClose, uVolume from etfdata where date >'" + string_date + "' ORDER BY date DESC;", server.serverSite) points_df = etf_ta(etf_data) current_port_value = float(apis.alpacaApi.get_account().portfolio_value) #Calculate how much of the portfolio should be weighted for the etf in question. points_df["etfweight"] = points_df.points / sum(points_df.points) #Calculate how many shares I should have at the start of the day. points_df["sumshares"] = ((current_port_value * points_df.etfweight) / points_df.last_close).astype(int) current_port_balance = apis.alpacaApi.list_positions() #If there are current positions, compare the difference is weighting if not buy the whole lot. if len(current_port_balance) > 0: current_bal = [] for pos in current_port_balance: current_bal.append([pos.symbol, pos.qty, pos.side]) current_bal_df = pd.DataFrame(current_bal, columns=["symbol", "qty", "side"]) merged_df = current_bal_df.merge(points_df, left_on="symbol", right_on="symbol") merged_df[ "posdifference"] = merged_df.sumshares - merged_df.qty.astype(int) else: merged_df = points_df[["symbol", "sumshares"]] merged_df.columns = ["symbol", "posdifference"] merged_df = merged_df[["symbol", "posdifference"]] return merged_df
def check_stoploss(current_trades, ema_time_period, server, apis, algo="charlie"): #Note to self. Search all data at once, not every stock for themself. #Find stop prices for the trades. for trade in current_trades: if (trade.stopPrice == 0): data = db.read_from_database( "Select distinct date, ticker, uHigh, uLow, uClose from dailydata where ticker ='" + trade.ticker + "' ORDER BY date DESC limit " + str(ema_time_period + 10) + ";", server.serverSite) #Talib need the oldest data to be first data = data.iloc[::-1] #Setting the stop price to the 20EMA data["stop_price"] = talib.EMA(data.uClose, timeperiod=ema_time_period) trade.setStopPrice(data.stop_price[0]) logging.info("Stop price for ", trade.ticker, " is set to ", trade.stopPrice, "entry:", trade.entryPrice) else: #Get the close price of the last 5 minute candle and comapre it against the stop price #If the 5min candle has closed above the stop price, it will flatten the trade. #current_trade_price = apis.alpacaApi.get_barset(trade.ticker,"5Min",limit = 1).df.iloc[0,3] current_trade_price = trade.last15MinCandle.iloc[0, 3] if (current_trade_price > trade.stopPrice and trade.orderSide == "sell"): trade.flattenOrder(action="Stoploss", apis=apis, server=server, algo=algo) current_trades.remove(trade) if (current_trade_price < trade.stopPrice and trade.orderSide == "buy"): trade.flattenOrder(action="Stoploss", apis=apis, server=server, algo=algo) current_trades.remove(trade) return current_trades
def bb_cross(server): #This function looks at the bollinger bands. If a stock closes below or above the upper /lower bollinger band we will execute a trade if the trend is in our favour #We are using the 50SMA to look at the current trend of the stock. #I belive it would be pretty rare for this to find a buy. watchlist = [] tickers = db.read_snp_tickers(server.serverSite).Symbol.tolist() for ticker in tickers: try: data = db.read_from_database( "Select date, ticker,uOpen, uHigh, uLow, uClose from dailydata where ticker ='" + ticker + "' ORDER BY date DESC limit 100;", server.serverSite) #Talib need the oldest data to be first data = data.iloc[::-1] data["SMA50"] = talib.SMA(data.uClose, timeperiod=50) data["BBupper"], data["BBmiddle"], data["BBlower"] = talib.BBANDS( data.uClose, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) #Using default params #Has the stock peaked above Upper BB and we are downtrending? -> Short if data.BBupper[0] < data.uHigh[0] and data.SMA50[0] < data.SMA50[ 2]: watchlist.append([ticker, "sell", data.Low[0], "BB"]) logging.info("Found BB crossings for ", ticker) #Has the stock peaked below lower BB and we are uptrending? -> Buy if data.BBlower[0] > data.uLow[0] and data.SMA50[0] > data.SMA50[2]: watchlist.append([ticker, "buy", data.uHigh[0], "BB"]) logging.info("Found BB crossings for ", ticker) except: logging.info("Database fetch has failed for ticker ", ticker) #Returns an list of lists with ticker, enrty price and strategy return watchlist
def find_ma_crossovers(serverSite): crossovers = [] bt_tickers = read_from_database("SELECT DISTINCT ticker FROM backtestdata;",serverSite).ticker.tolist() for ticker in bt_tickers: bt_data = read_from_database("SELECT ticker, timestamp, open, high ,low, close, volume FROM backtestdata WHERE ticker ='"+ticker+"';",serverSite) #Talib need the oldest data to be first bt_data = bt_data.iloc[::-1] bt_data["EMA"+str(9)] = talib.EMA(bt_data.close, timeperiod = 9) bt_data["EMA"+str(20)] = talib.EMA(bt_data.close, timeperiod = 20) bt_data["EMA"+str(50)] = talib.SMA(bt_data.close, timeperiod = 50) bt_data["EMA"+str(100)] = talib.SMA(bt_data.close, timeperiod = 100) bt_data["EMA"+str(200)] = talib.SMA(bt_data.close, timeperiod = 200) bt_data["MACD"],bt_data["MACDsignal"], bt_data["MACDhist"] = talib.MACD(bt_data.close) #Using default params bt_data["RSI"] = talib.RSI(bt_data.close) #Using default params bt_data["ATR"] = talib.ATR(bt_data.high, bt_data.low,bt_data.close) bt_data["TATR"] = talib.TRANGE(bt_data.high, bt_data.low,bt_data.close) bt_data["BBUpper"],bt_data["BBmiddle"], bt_data["BBlower"] = talib.BBANDS(bt_data.close, timeperiod=20, nbdevup=2, nbdevdn=2, matype=0) #Using default params bt_data["dojiDH"] = talib.CDLDRAGONFLYDOJI(bt_data.open, bt_data.high, bt_data.low, bt_data.close) bt_data["hammer"] = talib.CDLHAMMER(bt_data.open, bt_data.high, bt_data.low, bt_data.close) bt_data["CDLDOJI"] = talib.CDLDOJI(bt_data.open, bt_data.high, bt_data.low, bt_data.close) #Dropping NAs bt_data.dropna(inplace = True) #Find the crossovers #Extremely bad solution. Im sure there are better ways crossAbove = [] crossBelow = [] for key, row in enumerate(bt_data.iterrows()): if(bt_data.iloc[key,5] > bt_data.iloc[key,8] and bt_data.iloc[key-1,5] < bt_data.iloc[key-1,8]): crossAbove.append(True) else: crossAbove.append(False) for key, row in enumerate(bt_data.iterrows()): if(bt_data.iloc[key,5] < bt_data.iloc[key,8] and bt_data.iloc[key-1,5] > bt_data.iloc[key-1,8]): crossBelow.append(True) else: crossBelow.append(False) bt_data["crossBelow"] = crossBelow bt_data["crossAbove"] = crossAbove class Trade: def __init__(self,ticker, targetEntry, stoploss, crossrow, active = True): self.ticker = ticker self.targetEntry = targetEntry self.actualEntry = 0 self.stoploss = stoploss self.target = 0 self.crossrow = crossrow self.searching_for_entry = True self.active = active def tradeFoundLong(self,actualEntry): self.actualEntry = actualEntry self.target = self.actualEntry + (self.actualEntry- self.stoploss) * 2 self.searching_for_entry = False #print(self.entry, self.target, self.stoploss) def tradeFoundShort(self,actualEntry): self.actualEntry = actualEntry self.target = self.actualEntry - (self.stoploss - self.actualEntry) * 2 self.searching_for_entry = False def deactivateTrade(self): self.active = False #Looking at the longs! #Check if hit stoploss or target count_target = 0 count_stop = 0 count_started_trade = 0 active_trade = Trade("Ticker",1,1,1, active = False) #Dummy trade, not important for result but excecution needs once to start with. for key, row in enumerate(bt_data.iterrows()): if (row[1].crossAbove): active_trade = Trade(ticker, targetEntry = row[1].high, stoploss = row[1].EMA20 , crossrow = row[0]) print("Started search at row",row[0]) #Enter at open if there has been a big gap durin pre and post market, othervise assume we enter at the highs if (active_trade.targetEntry < row[1].high and active_trade.searching_for_entry and active_trade.active): if (row[1].open > active_trade.targetEntry): active_trade.tradeFoundLong(actualEntry = row[1].open) else: (active_trade.tradeFoundLong(actualEntry = active_trade.targetEntry)) print("Started trade at row", row[0], "from", active_trade.crossrow) count_started_trade += 1 #Assume if it the candle hits out target we get out if (active_trade.target < row[1].high and active_trade.searching_for_entry == False and active_trade.active): active_trade.deactivateTrade() crossovers.append([active_trade.ticker, active_trade.crossrow,"Target"]) print("Target met at row", row[0], " from row ", active_trade.crossrow) count_target += 1 #If the candle closes above our stop, stop out if (active_trade.stoploss > row[1].close and active_trade.searching_for_entry == False and active_trade.active): active_trade.deactivateTrade() crossovers.append([active_trade.ticker, active_trade.crossrow,"Stoploss"]) print("Stoploss met at row", row[0], " from row ", active_trade.crossrow) count_stop += 1 print("Trades started:",count_started_trade ,"Stops:", count_stop, "Targets:",count_target,"from total", sum(bt_data.crossAbove)) #Shorts!! count_target = 0 count_stop = 0 count_started_trade = 0 active_trade = Trade("Ticker",1,1,1, active = False) #Dummy trade, not important for result but excecution needs once to start with. for key, row in enumerate(bt_data.iterrows()): if (row[1].crossBelow): active_trade = Trade(ticker,targetEntry = row[1].low, stoploss = row[1].EMA20 , crossrow = row[0]) print("Started search at row",row[0]) #Enter at open if there has been a big gap durin pre and post market, othervise assume we enter at the lows if (active_trade.targetEntry < row[1].low and active_trade.searching_for_entry and active_trade.active): if (row[1].open < active_trade.targetEntry): active_trade.tradeFoundShort(actualEntry = row[1].open) else: (active_trade.tradeFoundShort(actualEntry = active_trade.targetEntry)) print("Started trade at row", row[0], "from", active_trade.crossrow) count_started_trade += 1 #Assume if it the candle hits out target we get out if (active_trade.target < row[1].low and active_trade.searching_for_entry == False and active_trade.active): active_trade.deactivateTrade() crossovers.append([active_trade.ticker, active_trade.crossrow,"Target"]) print("Target met at row", row[0], " from row ", active_trade.crossrow) count_target += 1 #If the candle closes above our stop, stop out if (active_trade.stoploss < row[1].close and active_trade.searching_for_entry == False and active_trade.active): active_trade.deactivateTrade() crossovers.append([active_trade.ticker, active_trade.crossrow,"Stoploss"]) print("Stoploss met at row", row[0], " from row ", active_trade.crossrow) count_stop += 1 print("Trades started:",count_started_trade ,"Stops:", count_stop, "Targets:",count_target,"from total", sum(bt_data.crossAbove)) return crossovers
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 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)