Removing strategy logic from swing trading dashboard
This commit is contained in:
parent
cb95eb5bc6
commit
fd190c36bc
@ -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
|
@ -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)
|
@ -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
|
@ -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
|
@ -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')
|
@ -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')
|
@ -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
|
@ -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
|
@ -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)
|
@ -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')
|
@ -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
|
@ -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')
|
@ -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')
|
@ -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
|
@ -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)
|
@ -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')
|
@ -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)
|
@ -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
|
@ -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
|
@ -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
|
@ -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)
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue
Block a user