Spaces:
Running
Running
Create signals/strategy.py
Browse files- signals/strategy.py +68 -0
signals/strategy.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# signals/strategy.py
|
2 |
+
|
3 |
+
def indicator_signal_ema(data, short_period=12, long_period=26):
|
4 |
+
"""Calculate EMA signals: buy, sell, neutral."""
|
5 |
+
ema_short = data['Close'].ewm(span=short_period, adjust=False).mean()
|
6 |
+
ema_long = data['Close'].ewm(span=long_period, adjust=False).mean()
|
7 |
+
data['EMA_Short'] = ema_short
|
8 |
+
data['EMA_Long'] = ema_long
|
9 |
+
data['EMA_Signal'] = 'neutral'
|
10 |
+
data.loc[ema_short > ema_long, 'EMA_Signal'] = 'buy'
|
11 |
+
data.loc[ema_short < ema_long, 'EMA_Signal'] = 'sell'
|
12 |
+
return data
|
13 |
+
|
14 |
+
def indicator_signal_macd(data, fast_period=12, slow_period=26, signal_period=9):
|
15 |
+
"""Calculate MACD signals: buy, sell, neutral."""
|
16 |
+
exp1 = data['Close'].ewm(span=fast_period, adjust=False).mean()
|
17 |
+
exp2 = data['Close'].ewm(span=slow_period, adjust=False).mean()
|
18 |
+
macd = exp1 - exp2
|
19 |
+
signal_line = macd.ewm(span=signal_period, adjust=False).mean()
|
20 |
+
data['MACD'] = macd
|
21 |
+
data['MACD_Signal_Line'] = signal_line
|
22 |
+
data['MACD_Signal'] = 'neutral'
|
23 |
+
data.loc[macd > signal_line, 'MACD_Signal'] = 'buy'
|
24 |
+
data.loc[macd < signal_line, 'MACD_Signal'] = 'sell'
|
25 |
+
return data
|
26 |
+
|
27 |
+
def indicator_signal_rsi(data, period=14, overbought=70, oversold=30):
|
28 |
+
"""Calculate RSI signals: buy, sell, neutral."""
|
29 |
+
delta = data['Close'].diff(1)
|
30 |
+
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
|
31 |
+
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
|
32 |
+
rs = gain / loss
|
33 |
+
rsi = 100 - (100 / (1 + rs))
|
34 |
+
data['RSI'] = rsi
|
35 |
+
data['RSI_Signal'] = 'neutral'
|
36 |
+
data.loc[rsi < oversold, 'RSI_Signal'] = 'buy'
|
37 |
+
data.loc[rsi > overbought, 'RSI_Signal'] = 'sell'
|
38 |
+
return data
|
39 |
+
|
40 |
+
def indicator_signal_bollinger_bands(data, period=20, std_dev=2):
|
41 |
+
"""Calculate Bollinger Band signals: buy, sell, neutral."""
|
42 |
+
sma = data['Close'].rolling(window=period).mean()
|
43 |
+
std = data['Close'].rolling(window=period).std()
|
44 |
+
upper_band = sma + (std_dev * std)
|
45 |
+
lower_band = sma - (std_dev * std)
|
46 |
+
data['BB_Upper'] = upper_band
|
47 |
+
data['BB_Lower'] = lower_band
|
48 |
+
data['BB_Signal'] = 'neutral'
|
49 |
+
data.loc[data['Close'] < lower_band, 'BB_Signal'] = 'buy'
|
50 |
+
data.loc[data['Close'] > upper_band, 'BB_Signal'] = 'sell'
|
51 |
+
return data
|
52 |
+
|
53 |
+
def generate_combined_signals(data):
|
54 |
+
"""Combine signals from all indicators and generate final buy/sell signals."""
|
55 |
+
data = indicator_signal_ema(data)
|
56 |
+
data = indicator_signal_macd(data)
|
57 |
+
data = indicator_signal_rsi(data)
|
58 |
+
data = indicator_signal_bollinger_bands(data)
|
59 |
+
|
60 |
+
# Analyze signals from all indicators
|
61 |
+
signals = ['EMA_Signal', 'MACD_Signal', 'RSI_Signal', 'BB_Signal']
|
62 |
+
data['Combined_Signal'] = data.apply(lambda row: 'buy' if sum(row[signal] == 'buy' for signal in signals) >= 3
|
63 |
+
else ('sell' if sum(row[signal] == 'sell' for signal in signals) >= 3 else 'neutral'), axis=1)
|
64 |
+
return data
|
65 |
+
|
66 |
+
# Note: This script assumes the 'data' DataFrame contains a 'Close' column with the closing prices.
|
67 |
+
# You will need to replace the placeholder calculation functions with the actual implementations
|
68 |
+
# from your indicators package.
|