import pandas as pd from datetime import datetime, time from pytz import timezone from time import sleep import math def in_timeframe(): now = datetime.now(timezone('US/Eastern')).time() day = datetime.today().weekday() return (now >= time(9,30) and now < time(16)) and (day < 5 and day >= 0) def get_position(exchange, symbol): positions = exchange.fetch_positions([symbol]) for pos in positions: if pos['symbol'] == symbol and float(pos['contracts']) != 0: position_info = pos in_position = True long = pos['side'] == 'long' return position_info, in_position, long return {}, False, None def get_candle_df(exchange, symbol, timeframe, limit=55): ohlcv = pd.DataFrame( exchange.fetch_ohlcv(symbol, timeframe, limit=limit), columns=['time', 'open', 'high', 'low', 'close', 'volume'] ).set_index('time') return ohlcv def calc_tr(df): df['True_Range'] = df.ta.atr() return df['True_Range'].iloc[-1] def calc_atr(df, length=None): df['ATR'] = df.ta.atr(length=length) def calc_sup_res(df, length=20): df['support'] = df['low'].rolling(window=length).min() df['resistance'] = df['high'].rolling(window=length).max() return df['support'].iloc[-1], df['resistance'].iloc[-1] def hit_target(price, tp, sl, long: bool): if long: if price >= tp: print('TAKE PROFIT REACHED, CLOSING POSITION') return True elif price <= sl: print('STOP LOSS REACHED, CLOSING POSITION') return True else: if price <= tp: print('TAKE PROFIT REACHED, CLOSING POSITION') return True elif price >= sl: print('STOP LOSS REACHED, CLOSING POSITION') return True return False def close_position(exchange, symbol): exchange.cancel_all_orders(symbol) position, in_position, long = get_position(exchange, symbol) while in_position: ticker = exchange.fetch_ticker(symbol) if long: bid = ticker['bid'] exchange.create_limit_sell_order( symbol, position['contracts'], bid, {'timeInForce': 'GTC', 'reduceOnly': True} ) print(f'SELL to close: {position["contracts"]} {symbol} at {bid}') else: ask = ticker['ask'] exchange.create_limit_buy_order( symbol, position['contracts'], ask, {'timeInForce': 'GTC', 'reduceOnly': True} ) print(f'BUY to close: {position["contracts"]} {symbol} at {ask}') sleep(30) position, in_position, long = get_position(exchange, symbol) exchange.cancel_all_orders(symbol) sleep(60) def end_of_trading_week(): now = datetime.now(timezone('US/Eastern')).time() day = datetime.today().weekday() return day == 4 and now >= time(16) and now < time(16,1) def get_extreme_of_consolidation(df, percent): for index, row in df.iloc[::-1].iterrows(): if (row['True_Range'] / row['close']) * 100 > percent: consolidation_data = df[df.index > index] return consolidation_data.low.min(), consolidation_data.high.max() return df.low.min(), df.high.max() def calc_stoch_rsi(df, lookback=14): rsi = df.ta.rsi(length=lookback) min_rsi = rsi.tail(lookback).min() max_rsi = rsi.tail(lookback).max() df['stoch_rsi'] = (rsi.iloc[-1] - min_rsi) / (max_rsi - min_rsi) def calc_nadarya(df, bandwidth=8, source='close'): src = df[source] out = [] for i, v1 in src.items(): tsum = 0 sumw = 0 for j, v2 in src.items(): w = math.exp(-(math.pow(i-j, 2) / (bandwidth * bandwidth * 2))) tsum += v2 * w sumw += w out.append(tsum / sumw) df['nadarya'] = out d = df['nadarya'].rolling(window=2).apply(lambda x: x.iloc[1] - x.iloc[0]) df['nadarya_buy'] = (d > 0) & (d.shift(1) < 0) df['nadarya_sell'] = (d < 0) & (d.shift(1) > 0) return df['nadarya_buy'].iloc[-1], df['nadarya_sell'].iloc[-1] def is_oversold(rsi, window=14, times=1, target=10): rsi_window = rsi.tail(window) rsi_crossed = [ v for ind, v in enumerate(rsi_window.values) if v <= target and rsi_window.values[ind-1] >= target and ind > 0 ] return len(rsi_crossed) >= times def is_overbought(rsi, window=14, times=1, target=90): rsi_window = rsi.tail(window) rsi_crossed = [ v for ind, v in enumerate(rsi_window.values) if v >= target and rsi_window.values[ind-1] <= target and ind > 0 ] return len(rsi_crossed) >= times