File size: 3,128 Bytes
4be2d4d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
๊ธฐ์ˆ ์  ์ง€ํ‘œ ๊ณ„์‚ฐ ๊ด€๋ จ ํ•จ์ˆ˜ ๋ชจ์Œ
"""

import numpy as np
import pandas as pd

def calculate_ema_series(series, span):
    """์ฃผ์–ด์ง„ Series์— ๋Œ€ํ•ด ์ง€์ˆ˜์ด๋™ํ‰๊ท (EMA)์„ ๊ณ„์‚ฐ"""
    return series.ewm(span=span, adjust=False).mean()

def calculate_macd(data, short_span, long_span, signal_span):
    """MACD, Signal Line ๊ณ„์‚ฐ"""
    ema_short = calculate_ema_series(data['Close'], short_span)
    ema_long = calculate_ema_series(data['Close'], long_span)
    macd = ema_short - ema_long
    signal = calculate_ema_series(macd, signal_span)
    return macd, signal

def calculate_cmf(data, period):
    """Chaikin Money Flow ๊ณ„์‚ฐ"""
    high = data['High']
    low = data['Low']
    close = data['Close']
    volume = data['Volume']
    
    # Money Flow Multiplier
    mf_multiplier = ((close - low) - (high - close)) / (high - low).replace(0, 0.0001)
    
    # Money Flow Volume
    mf_volume = mf_multiplier * volume
    
    # Chaikin Money Flow
    cmf = mf_volume.rolling(window=period).sum() / volume.rolling(window=period).sum()
    
    # ๊ฒฐ๊ณผ ์ €์žฅ
    data[f'CMF_{period}'] = cmf
    return data

def calculate_rsi(data, period=14):
    """RSI ๊ณ„์‚ฐ"""
    close = data['Close']
    delta = close.diff()
    
    # ์ƒ์Šน/ํ•˜๋ฝ ๋ถ„๋ฆฌ
    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)
    
    # ํ‰๊ท  ๊ณ„์‚ฐ
    avg_gain = gain.rolling(window=period).mean()
    avg_loss = loss.rolling(window=period).mean()
    
    # RS ๊ณ„์‚ฐ
    rs = avg_gain / avg_loss.replace(0, 1e-10)  # 0์œผ๋กœ ๋‚˜๋ˆ„๊ธฐ ๋ฐฉ์ง€
    
    # RSI ๊ณ„์‚ฐ
    rsi = 100 - (100 / (1 + rs))
    
    # ๊ฒฐ๊ณผ ์ €์žฅ
    data[f'RSI_{period}'] = rsi
    return data


# -----------------------------
# ๊ธฐ์ˆ ์  ์ง€ํ‘œ ์ถ”๊ฐ€ ํ•จ์ˆ˜
# -----------------------------
def add_technical_indicators(df, ema_params, macd_params, cmf_period, rsi_params):
    """
    ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ์— ์ตœ์ ํ™”๋œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ชจ๋“  ๊ธฐ์ˆ ์  ์ง€ํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜
    """
    # EMA ๊ณ„์‚ฐ
    df['EMA_short'] = calculate_ema_series(df['Close'], ema_params['short'])
    df['EMA_long'] = calculate_ema_series(df['Close'], ema_params['long'])
    df['EMA_diff'] = df['EMA_short'] - df['EMA_long']
    
    # MACD ๊ณ„์‚ฐ
    ema_fast = calculate_ema_series(df['Close'], macd_params['fast'])
    ema_slow = calculate_ema_series(df['Close'], macd_params['slow'])
    df['MACD'] = ema_fast - ema_slow
    df['MACD_signal'] = calculate_ema_series(df['MACD'], macd_params['signal'])
    df['MACD_diff'] = df['MACD'] - df['MACD_signal']
    
    # CMF ๊ณ„์‚ฐ
    df = calculate_cmf(df, cmf_period)
    df['CMF'] = df[f'CMF_{cmf_period}']
    df.drop(columns=[f'CMF_{cmf_period}'], inplace=True)

    # RSI ๊ณ„์‚ฐ
    df = calculate_rsi(df, rsi_params['period'])
    df['RSI'] = df[f'RSI_{rsi_params["period"]}']

    df.drop(columns=[f'RSI_{rsi_params["period"]}'], inplace=True)
    
    # RSI ์ž„๊ณ„๊ฐ’ ์ €์žฅ
    df['RSI_upper'] = rsi_params['upper_threshold']
    df['RSI_lower'] = rsi_params['lower_threshold']
    
    # ์ˆ˜์ต๋ฅ  ๊ณ„์‚ฐ
    df['Return'] = df['Close'].pct_change()
    
    return df