Removing strategy logic from swing trading dashboard

This commit is contained in:
moshferatu 2024-11-27 12:42:19 -08:00
parent cb95eb5bc6
commit fd190c36bc
26 changed files with 0 additions and 638 deletions

View File

@ -1,22 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the Advance / Decline Ratio strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
above_200_ma = data['Close'] > data['Close'].rolling(window = 200).mean()
start_date = data['Date'].min()
end_date = data['Date'].max()
advances = get_daily_data(symbol = 'IINA.Z', start_date = start_date, end_date = end_date)
declines = get_daily_data(symbol = 'IIND.Z', start_date = start_date, end_date = end_date)
ratio = advances['Close'] / declines['Close']
ratio_greater_than_2 = ratio >= 2
signals = Series('N', index = data.index)
signals[above_200_ma & ratio_greater_than_2] = 'L'
return signals

View File

@ -1,45 +0,0 @@
import pandas as pd
import numpy as np
from pandas import DataFrame, Series
def calculate_moving_average(data: DataFrame, window: int = 200) -> Series:
"""
Calculate the 200-day moving average and return it as a Series without modifying the original DataFrame.
"""
return data['Close'].rolling(window = window).mean()
def calculate_rsi(data: DataFrame, period: int = 2) -> Series:
"""
Calculate the 2-period RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = pd.Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = pd.Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def calculate_cumulative_rsi(rsi: Series, window: int = 2) -> Series:
"""
Calculate the cumulative RSI over a specified window period and return it as a Series.
"""
return rsi.rolling(window = window).sum()
def signals(data: DataFrame, rsi_period: int = 2, cumulative_period: int = 2) -> Series:
"""
Generate 'L'ong entry signals based on the Cumulative RSI strategy.
Returns a Series with 'L' for entry signals and 'N' otherwise without modifying the original DataFrame.
Entry Condition: 2-period cumulative RSI below 35 and above the 200-day moving average.
"""
ma_200 = calculate_moving_average(data)
rsi_2 = calculate_rsi(data, period = rsi_period)
cumulative_rsi_2 = calculate_cumulative_rsi(rsi_2, window = cumulative_period)
long_condition = (data['Close'] > ma_200) & (cumulative_rsi_2 < 35)
return Series(np.where(long_condition, 'L', 'N'), index = data.index)

View File

@ -1,22 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the Decline / Advance Ratio strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
above_200_ma = data['Close'] > data['Close'].rolling(window = 200).mean()
start_date = data['Date'].min()
end_date = data['Date'].max()
advances = get_daily_data(symbol = 'IINA.Z', start_date = start_date, end_date = end_date)
declines = get_daily_data(symbol = 'IIND.Z', start_date = start_date, end_date = end_date)
ratio = declines['Close'] / advances['Close']
ratio_greater_than_2 = ratio >= 2
signals = Series('N', index = data.index)
signals[above_200_ma & ratio_greater_than_2] = 'L'
return signals

View File

@ -1,22 +0,0 @@
import pandas as pd
def signals(data: pd.DataFrame) -> pd.Series:
"""
Generate trading signals based on the following rules:
1. SPY is above its 200-day moving average.
2. Enter a long position if SPY closes at a 5-day low.
This strategy is based on the Double 7's strategy by Larry Connors.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
low_5_day = data['Close'].rolling(window = 5).min()
above_200_ma = data['Close'] > ma_200
at_5_day_low = data['Close'] == low_5_day
signals = pd.Series('N', index = data.index)
signals[above_200_ma & at_5_day_low] = 'L'
return signals

View File

@ -1,11 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Generate signals for entering a long trade when the market's
close price is lower for 3 consecutive days.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
lower_close = data['Close'] < data['Close'].shift(1)
return (lower_close & lower_close.shift(1) & lower_close.shift(2)).apply(lambda x: 'L' if x else 'N')

View File

@ -1,8 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Calculate the End of Month (EOM) signal.
Returns a Series with 'L' for long signals if the date is close to the end of the month and 'N' otherwise.
"""
return data['Date'].apply(lambda x: 'L' if x.day in [23, 24, 25, 26, 27] else 'N')

View File

@ -1,17 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Generate swing trading signals based on the High Volume Days strategy.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
data['200_MA'] = data['Close'].rolling(window = 200).mean()
above_200_ma = data['Close'] > data['200_MA']
highest_volume = data['Volume'] == data['Volume'].rolling(window = 5).max()
close_lower_than_open = data['Close'] < data['Open']
signal_condition = above_200_ma & highest_volume & close_lower_than_open
signals = signal_condition.apply(lambda condition: 'L' if condition else 'N')
return signals

View File

@ -1,23 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate signals based on the HILO Index Lows strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
above_200_ma = data['Close'] > data['Close'].rolling(window = 200).mean()
start_date = data['Date'].min()
end_date = data['Date'].max()
new_highs = get_daily_data(symbol = 'FINH.Z', start_date = start_date, end_date = end_date)
new_lows = get_daily_data(symbol = 'FINL.Z', start_date = start_date, end_date = end_date)
hilo_index = new_highs['Close'] - new_lows['Close']
hilo_5_day_low = hilo_index == hilo_index.rolling(window = 5).min()
signals = Series('N', index = data.index)
signals[above_200_ma & hilo_5_day_low] = 'L'
return signals

View File

@ -1,35 +0,0 @@
import numpy as np
import pandas as pd
def calculate_rsi(data: pd.DataFrame, period: int = 21) -> pd.Series:
"""
Calculate the RSI for a given period and return it as a Series.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = pd.Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = pd.Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def calculate_ibs(data: pd.DataFrame) -> pd.Series:
"""
Calculate the IBS and return it as a Series.
"""
return (data['Close'] - data['Low']) / (data['High'] - data['Low'])
def signals(data: pd.DataFrame) -> pd.Series:
"""
Generate swing trading signals based on the IBS + RSI strategy.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
ibs = calculate_ibs(data)
rsi_21 = calculate_rsi(data, period = 21)
conditions = (ibs < 0.25) & (rsi_21 < 45)
return pd.Series(np.where(conditions, 'L', 'N'), index = data.index)

View File

@ -1,9 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Calculate the Internal Bar Strength (IBS) signal.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
ibs_series = (data['Close'] - data['Low']) / (data['High'] - data['Low'])
return ibs_series.apply(lambda ibs: 'L' if ibs < 0.2 else 'N')

View File

@ -1,22 +0,0 @@
import pandas as pd
def signals(data: pd.DataFrame) -> pd.Series:
"""
Calculate swing trading signals based on Internal Bar Strength Band strategy.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
rolling_high_minus_low = (data['High'] - data['Low']).rolling(window = 25).mean()
rolling_high = data['High'].rolling(window = 10).max()
lower_band = rolling_high - 2.5 * rolling_high_minus_low
ibs = (data['Close'] - data['Low']) / (data['High'] - data['Low'])
signals = (
(data['Close'] > ma_200) &
(data['Close'] < lower_band) &
(ibs < 0.3)
).apply(lambda condition: 'L' if condition else 'N')
return signals

View File

@ -1,10 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Generate swing trading signals based the Large Moves (Down) strategy.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
percent_change = (data['Open'] - data['Close']) / data['Open']
return percent_change.apply(lambda change: 'L' if change >= 0.01 else 'N')

View File

@ -1,11 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Generate signals for entering a long trade when the market makes
a lower low for 2 consecutive days.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
lower_low = data['Low'].shift(1) > data['Low']
return (lower_low & lower_low.shift(1)).apply(lambda x: 'L' if x else 'N')

View File

@ -1,27 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate signals based on the Put / Call Ratio Highs strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
above_200_ma = data['Close'] > data['Close'].rolling(window = 200).mean()
start_date = data['Date'].min()
end_date = data['Date'].max()
put_volume = get_daily_data(symbol = 'VPOT.Z', start_date = start_date, end_date = end_date)
call_volume = get_daily_data(symbol = 'VCOT.Z', start_date = start_date, end_date = end_date)
# The put and call volume data contains extraneous data for holidays when the market is closed.
put_volume = put_volume[put_volume['Date'].isin(data['Date'])].reset_index(drop = True)
call_volume = call_volume[call_volume['Date'].isin(data['Date'])].reset_index(drop = True)
put_call_ratio = put_volume['Close'] / call_volume['Close']
put_call_high_5_day = put_call_ratio == put_call_ratio.rolling(window = 5).max()
signals = Series('N', index = data.index)
signals[above_200_ma & put_call_high_5_day] = 'L'
return signals

View File

@ -1,38 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
def calculate_moving_average(data: DataFrame, window: int = 200) -> Series:
"""
Calculate the moving average and return it as a Series.
"""
return data['Close'].rolling(window=window).mean()
def calculate_rsi(data: DataFrame, period: int = 4) -> Series:
"""
Calculate the RSI and return it as a Series.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha=alpha, adjust=False).mean()
avg_loss = Series(loss).ewm(alpha=alpha, adjust=False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Calculate signals for the RSI PowerZones strategy.
Returns a Series with 'L' for long signals and 'N' otherwise.
"""
ma_200 = calculate_moving_average(data, window = 200)
rsi_4 = calculate_rsi(data, period = 4)
above_ma_200 = data['Close'] > ma_200
rsi_below_30 = rsi_4 < 30
conditions = above_ma_200 & rsi_below_30
return Series(np.where(conditions, 'L', 'N'), index = data.index)

View File

@ -1,10 +0,0 @@
from pandas import DataFrame, Series
def signals(data: DataFrame) -> Series:
"""
Generate signals for entering a long trade when the market makes a 10-day low.
Returns a series with 'L' for long signals and 'N' otherwise.
"""
ten_day_low = data['Low'] == data['Low'].rolling(window = 10, min_periods = 10).min()
return ten_day_low.apply(lambda x: 'L' if x else 'N')

View File

@ -1,40 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
def calculate_moving_average(data: DataFrame, window: int = 200) -> Series:
"""
Calculate the 200-period moving average and return it as a Series without modifying the original DataFrame.
"""
return data['Close'].rolling(window = window).mean()
def calculate_rsi(data: DataFrame, period: int = 2) -> Series:
"""
Calculate the 2-period RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Calculate signals based on the Time, Price, Scale-in (TPS) strategy.
Returns a Series with 'Long' for signals and 'None' otherwise, without modifying the original DataFrame.
"""
ma_200 = calculate_moving_average(data)
rsi_2 = calculate_rsi(data)
above_ma_200 = data['Close'] > ma_200
rsi_below_25 = (rsi_2 < 25)
rsi_below_25_for_two_days = rsi_below_25 & rsi_below_25.shift(1, fill_value = False)
conditions = above_ma_200 & rsi_below_25_for_two_days
return Series(np.where(conditions, 'L', 'N'), index = data.index)

View File

@ -1,46 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
from daily_data import get_daily_data
def calculate_rsi(data: DataFrame, period: int = 2) -> Series:
"""
Calculate the RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the TRIN strategy with the following rules:
1. SPY is above its 200-day moving average
2. 2-period RSI is below 50
3. TRIN closes above 1
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
rsi_2 = calculate_rsi(data, period = 2)
start_date = data['Date'].min()
end_date = data['Date'].max()
trin_data = get_daily_data(symbol = 'RINT.Z', start_date = start_date, end_date = end_date)
trin_above_1 = trin_data['Close'] > 1
above_200_ma = data['Close'] > ma_200
rsi_below_50 = rsi_2 < 50
signals = Series('N', index = data.index)
signals[above_200_ma & rsi_below_50 & trin_above_1] = 'L'
return signals

View File

@ -1,20 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the TRIN Thrusts strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
start_date = data['Date'].min()
end_date = data['Date'].max()
trin_data = get_daily_data(symbol = 'RINT.Z', start_date = start_date, end_date = end_date)
trin_change = trin_data['Close'].pct_change()
trin_30_below = trin_change <= -0.4
signals = Series('N', index = data.index)
signals[trin_30_below] = 'L'
return signals

View File

@ -1,16 +0,0 @@
from pandas import DataFrame, Series, to_datetime
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the day of the week and downward close conditions.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
date_series = to_datetime(data['Date'], errors = 'coerce')
monday_or_tuesday = date_series.dt.dayofweek.isin([0, 1])
lower_past_two_days = (data['Close'] < data['Close'].shift(1)) & (data['Close'].shift(1) < data['Close'].shift(2))
signals = Series('N', index=data.index)
signals[monday_or_tuesday & lower_past_two_days] = 'L'
return signals

View File

@ -1,35 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
def calculate_moving_average(data: DataFrame, window: int = 200) -> Series:
"""
Calculate the 200-period moving average and return it as a Series without modifying the original DataFrame.
"""
return data['Close'].rolling(window = window).mean()
def calculate_rsi(data: DataFrame, period: int = 2) -> Series:
"""
Calculate the 2-period RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Calculate signals based on the 200-period MA and 2-period RSI.
Returns a Series with 'Long' for signals and 'None' otherwise, without modifying the original DataFrame.
"""
ma_200 = calculate_moving_average(data)
rsi_2 = calculate_rsi(data)
conditions = (data['Close'] > ma_200) & (rsi_2 < 15)
return Series(np.where(conditions, 'L', 'N'), index = data.index)

View File

@ -1,23 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the VIX Above Moving Average strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
above_200_ma = data['Close'] > ma_200
start_date = data['Date'].min()
end_date = data['Date'].max()
vix_data = get_daily_data(symbol='VIX.XO', start_date = start_date, end_date = end_date)
vix_ma_10 = vix_data['Close'].rolling(window = 10).mean()
vix_close_10_percent_above_ma = vix_data['Close'] >= (1.1 * vix_ma_10)
signals = Series('N', index = data.index)
signals[above_200_ma & vix_close_10_percent_above_ma] = 'L'
return signals

View File

@ -1,23 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the VIX 15-day high strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
above_200_ma = data['Close'] > ma_200
start_date = data['Date'].min()
end_date = data['Date'].max()
vix_data = get_daily_data(symbol='VIX.XO', start_date=start_date, end_date=end_date)
vix_15_day_high = vix_data['High'] == vix_data['High'].rolling(window = 15).max()
vix_close_below_open = vix_data['Close'] < vix_data['Open']
signals = Series('N', index = data.index)
signals[above_200_ma & vix_15_day_high & vix_close_below_open] = 'L'
return signals

View File

@ -1,38 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
from daily_data import get_daily_data
def calculate_rsi(data: DataFrame, period: int = 5) -> Series:
"""
Calculate the RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Generate swing trading signals based on the Connors VIX Reversal 2 strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
start_date = data['Date'].min()
end_date = data['Date'].max()
vix_data = get_daily_data(symbol = 'VIX.XO', start_date = start_date, end_date = end_date)
vix_rsi_5 = calculate_rsi(vix_data, period = 5)
vix_rsi_above_70 = vix_rsi_5.shift(1) > 70
vix_close_below_prev_close = vix_data['Close'] < vix_data['Close'].shift(1)
signals = Series('N', index = data.index)
signals[vix_rsi_above_70 & vix_close_below_prev_close] = 'L'
return signals

View File

@ -1,21 +0,0 @@
from pandas import DataFrame, Series
from daily_data import get_daily_data
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the Connors VIX Reversal 3 strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
start_date = data['Date'].min()
end_date = data['Date'].max()
vix_data = get_daily_data(symbol = 'VIX.XO', start_date = start_date, end_date = end_date)
vix_ma_50 = vix_data['Close'].rolling(window = 50).mean()
vix_low_above_50_ma = vix_data['Low'] > vix_ma_50
vix_close_10_percent_above_ma = vix_data['Close'] >= (1.1 * vix_ma_50)
signals = Series('N', index = data.index)
signals[vix_low_above_50_ma & vix_close_10_percent_above_ma] = 'L'
return signals

View File

@ -1,44 +0,0 @@
import numpy as np
from pandas import DataFrame, Series
from daily_data import get_daily_data
def calculate_rsi(data: DataFrame, period: int = 2) -> Series:
"""
Calculate the RSI and return it as a Series without modifying the original DataFrame.
"""
delta = data['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
alpha = 1 / period
avg_gain = Series(gain).ewm(alpha = alpha, adjust = False).mean()
avg_loss = Series(loss).ewm(alpha = alpha, adjust = False).mean()
rs = avg_gain / avg_loss
return 100 - (100 / (1 + rs))
def signals(data: DataFrame) -> Series:
"""
Generate long signals based on the VIX RSI strategy.
Returns a Series with 'L' for long signals and 'N' for no signal.
"""
ma_200 = data['Close'].rolling(window = 200).mean()
rsi_2 = calculate_rsi(data, period = 2)
start_date = data['Date'].min()
end_date = data['Date'].max()
vix_data = get_daily_data(symbol = 'VIX.XO', start_date = start_date, end_date = end_date)
vix_rsi_2 = calculate_rsi(vix_data, period = 2)
above_200_ma = data['Close'] > ma_200
vix_rsi_above_90 = vix_rsi_2 > 90
vix_open_greater_than_prev_close = vix_data['Open'] > vix_data['Close'].shift(1)
rsi_below_30 = rsi_2 < 30
signals = Series('N', index = data.index)
signals[above_200_ma & vix_rsi_above_90 & vix_open_greater_than_prev_close & rsi_below_30] = 'L'
return signals