init
This commit is contained in:
@@ -89,6 +89,44 @@ def calculate_technical_indicators(data):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_daily_bollinger_distance(data):
|
||||
"""일봉 기준 볼린저 밴드 하단 근접도를 계산하여 distance, 하단 밴드, 종가를 반환한다."""
|
||||
# 데이터 인덱스가 datetime이 아니면 변환
|
||||
df = data.copy()
|
||||
if not isinstance(df.index, pd.DatetimeIndex):
|
||||
if 'datetime' in df.columns:
|
||||
df = df.set_index('datetime')
|
||||
# 일봉 리샘플링
|
||||
daily = df.resample('D').agg({'Open': 'first',
|
||||
'High': 'max',
|
||||
'Low': 'min',
|
||||
'Close': 'last',
|
||||
'Volume': 'sum'}).dropna()
|
||||
|
||||
# 볼린저 밴드 계산
|
||||
daily = calculate_bollinger_bands(daily)
|
||||
|
||||
if len(daily) < BOLLINGER_PERIOD:
|
||||
return None, None, None
|
||||
|
||||
latest_daily = daily.iloc[-1]
|
||||
|
||||
# 볼린저 밴드 값이 존재하는지 확인
|
||||
if pd.isna(latest_daily['Upper']) or pd.isna(latest_daily['Lower']):
|
||||
return None, None, None
|
||||
|
||||
upper_band = latest_daily['Upper']
|
||||
lower_band = latest_daily['Lower']
|
||||
current_price = latest_daily['Close']
|
||||
|
||||
# 밴드 폭이 0이면 계산 불가
|
||||
if upper_band - lower_band == 0:
|
||||
return None, None, None
|
||||
|
||||
distance = (current_price - lower_band) / (upper_band - lower_band)
|
||||
return distance, lower_band, current_price
|
||||
|
||||
def check_buy_signals(symbol, data):
|
||||
if len(data) < 60: # 최소 60일치 데이터 필요
|
||||
return None
|
||||
@@ -96,18 +134,25 @@ def check_buy_signals(symbol, data):
|
||||
latest = data.iloc[-1]
|
||||
prev = data.iloc[-2]
|
||||
|
||||
# 볼린저 밴드 신호
|
||||
bb_signal = False
|
||||
if isinstance(latest['Upper'], float):
|
||||
upper_band = latest['Upper']
|
||||
lower_band = latest['Lower']
|
||||
current_price = latest['Close']
|
||||
else:
|
||||
upper_band = latest['Upper'].iloc[0]
|
||||
lower_band = latest['Lower'].iloc[0]
|
||||
current_price = latest['Close'].iloc[0]
|
||||
|
||||
distance = (current_price - lower_band) / (upper_band - lower_band)
|
||||
# 볼린저 밴드 신호 (일봉 기준)
|
||||
distance, lower_band, current_price = get_daily_bollinger_distance(data)
|
||||
|
||||
if distance is None:
|
||||
# 일봉 볼린저 계산이 불가능한 경우 기존 주기 데이터를 사용
|
||||
if isinstance(latest['Upper'], float):
|
||||
upper_band = latest['Upper']
|
||||
lower_band = latest['Lower']
|
||||
current_price = latest['Close']
|
||||
else:
|
||||
upper_band = latest['Upper'].iloc[0]
|
||||
lower_band = latest['Lower'].iloc[0]
|
||||
current_price = latest['Close'].iloc[0]
|
||||
|
||||
if upper_band - lower_band != 0:
|
||||
distance = (current_price - lower_band) / (upper_band - lower_band)
|
||||
else:
|
||||
distance = 1 # 밴드폭이 0이면 신호 미충족으로 간주
|
||||
|
||||
bb_signal = distance < BOLLINGER_THRESHOLD
|
||||
|
||||
# U자 반등 후 이전 고점 돌파 여부 계산 (BREAKOUT)
|
||||
|
||||
Reference in New Issue
Block a user