144 lines
No EOL
4.7 KiB
Python
144 lines
No EOL
4.7 KiB
Python
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 |