File size: 6,232 Bytes
bfa4e15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import numpy as np
import pandas as pd

def identify_patterns(df):
    """Identify candlestick patterns in the data using basic calculations"""
    patterns = pd.DataFrame(index=df.index)

    # Calculate basic candlestick properties
    body = df['Close'] - df['Open']
    body_abs = abs(body)
    upper_shadow = df['High'] - df[['Open', 'Close']].max(axis=1)
    lower_shadow = df[['Open', 'Close']].min(axis=1) - df['Low']

    # 1. Hammer Pattern
    patterns['HAMMER'] = np.where(
        (lower_shadow > 2 * body_abs) &  # Long lower shadow
        (upper_shadow <= 0.1 * body_abs) &  # Minimal upper shadow
        (body > 0),  # Bullish close
        1, 0
    )

    # 2. Inverted Hammer Pattern
    patterns['INVERTED_HAMMER'] = np.where(
        (upper_shadow > 2 * body_abs) &  # Long upper shadow
        (lower_shadow <= 0.1 * body_abs) &  # Minimal lower shadow
        (body > 0),  # Bullish close
        1, 0
    )

    # 3. Piercing Line Pattern
    patterns['PIERCING_LINE'] = np.where(
        (body.shift(1) < 0) &  # Previous candle bearish
        (body > 0) &  # Current candle bullish
        (df['Open'] < df['Close'].shift(1)) &  # Opens below previous close
        (df['Close'] > (df['Open'].shift(1) + df['Close'].shift(1)) / 2),  # Closes above midpoint
        1, 0
    )

    # 4. Bullish Engulfing Pattern
    patterns['BULLISH_ENGULFING'] = np.where(
        (body.shift(1) < 0) &  # Previous candle bearish
        (body > 0) &  # Current candle bullish
        (df['Open'] < df['Close'].shift(1)) &  # Opens below previous close
        (df['Close'] > df['Open'].shift(1)),  # Closes above previous open
        1, 0
    )

    # 5. Morning Star Pattern
    patterns['MORNING_STAR'] = np.where(
        (body.shift(2) < 0) &  # First candle bearish
        (abs(body.shift(1)) < abs(body.shift(2)) * 0.3) &  # Second candle small
        (body > 0) &  # Third candle bullish
        (df['Close'] > df['Close'].shift(2) * 0.5),  # Closes above midpoint
        1, 0
    )

    # 6. Three White Soldiers
    patterns['THREE_WHITE_SOLDIERS'] = np.where(
        (body > 0) &  # Current candle bullish
        (body.shift(1) > 0) &  # Previous candle bullish
        (body.shift(2) > 0) &  # Two candles ago bullish
        (df['Close'] > df['Close'].shift(1)) &  # Each closes higher
        (df['Close'].shift(1) > df['Close'].shift(2)),
        1, 0
    )

    # 7. Bullish Harami
    patterns['BULLISH_HARAMI'] = np.where(
        (body.shift(1) < 0) &  # Previous candle bearish
        (body > 0) &  # Current candle bullish
        (df['Open'] > df['Close'].shift(1)) &  # Opens inside previous body
        (df['Close'] < df['Open'].shift(1)),  # Closes inside previous body
        1, 0
    )

    # 8. Hanging Man
    patterns['HANGING_MAN'] = np.where(
        (lower_shadow > 2 * body_abs) &  # Long lower shadow
        (upper_shadow <= 0.1 * body_abs) &  # Minimal upper shadow
        (body < 0),  # Bearish close
        1, 0
    )

    # 9. Dark Cloud Cover
    patterns['DARK_CLOUD_COVER'] = np.where(
        (body.shift(1) > 0) &  # Previous candle bullish
        (body < 0) &  # Current candle bearish
        (df['Open'] > df['High'].shift(1)) &  # Opens above previous high
        (df['Close'] < (df['Open'].shift(1) + df['Close'].shift(1)) / 2),  # Closes below midpoint
        1, 0
    )

    # 10. Bearish Engulfing
    patterns['BEARISH_ENGULFING'] = np.where(
        (body.shift(1) > 0) &  # Previous candle bullish
        (body < 0) &  # Current candle bearish
        (df['Open'] > df['Close'].shift(1)) &  # Opens above previous close
        (df['Close'] < df['Open'].shift(1)),  # Closes below previous open
        1, 0
    )

    # 11. Evening Star
    patterns['EVENING_STAR'] = np.where(
        (body.shift(2) > 0) &  # First candle bullish
        (abs(body.shift(1)) < abs(body.shift(2)) * 0.3) &  # Second candle small
        (body < 0) &  # Third candle bearish
        (df['Close'] < df['Close'].shift(2) * 0.5),  # Closes below midpoint
        1, 0
    )

    # 12. Three Black Crows
    patterns['THREE_BLACK_CROWS'] = np.where(
        (body < 0) &  # Current candle bearish
        (body.shift(1) < 0) &  # Previous candle bearish
        (body.shift(2) < 0) &  # Two candles ago bearish
        (df['Close'] < df['Close'].shift(1)) &  # Each closes lower
        (df['Close'].shift(1) < df['Close'].shift(2)),
        1, 0
    )

    # 13. Shooting Star
    patterns['SHOOTING_STAR'] = np.where(
        (upper_shadow > 2 * body_abs) &  # Long upper shadow
        (lower_shadow <= 0.1 * body_abs) &  # Minimal lower shadow
        (body < 0),  # Bearish close
        1, 0
    )

    # 14. Doji Patterns
    patterns['DOJI'] = np.where(
        abs(body) <= 0.1 * (df['High'] - df['Low']),  # Very small body
        1, 0
    )

    # 15. Dragonfly Doji
    patterns['DRAGONFLY_DOJI'] = np.where(
        (abs(body) <= 0.1 * (df['High'] - df['Low'])) &  # Doji body
        (upper_shadow <= 0.1 * (df['High'] - df['Low'])) &  # Minimal upper shadow
        (lower_shadow >= 0.7 * (df['High'] - df['Low'])),  # Long lower shadow
        1, 0
    )

    # 16. Gravestone Doji
    patterns['GRAVESTONE_DOJI'] = np.where(
        (abs(body) <= 0.1 * (df['High'] - df['Low'])) &  # Doji body
        (lower_shadow <= 0.1 * (df['High'] - df['Low'])) &  # Minimal lower shadow
        (upper_shadow >= 0.7 * (df['High'] - df['Low'])),  # Long upper shadow
        1, 0
    )

    return patterns

def calculate_technical_indicators(df):
    """Calculate technical indicators for analysis"""
    # RSI
    delta = df['Close'].diff()
    gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
    rs = gain / loss
    df['RSI'] = 100 - (100 / (1 + rs))

    # MACD
    exp1 = df['Close'].ewm(span=12, adjust=False).mean()
    exp2 = df['Close'].ewm(span=26, adjust=False).mean()
    df['MACD'] = exp1 - exp2
    df['MACD_Signal'] = df['MACD'].ewm(span=9, adjust=False).mean()
    df['MACD_Hist'] = df['MACD'] - df['MACD_Signal']

    # Moving Averages
    df['SMA_20'] = df['Close'].rolling(window=20).mean()
    df['SMA_50'] = df['Close'].rolling(window=50).mean()

    return df