init
This commit is contained in:
@@ -89,6 +89,44 @@ def calculate_technical_indicators(data):
|
|||||||
|
|
||||||
return 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):
|
def check_buy_signals(symbol, data):
|
||||||
if len(data) < 60: # 최소 60일치 데이터 필요
|
if len(data) < 60: # 최소 60일치 데이터 필요
|
||||||
return None
|
return None
|
||||||
@@ -96,18 +134,25 @@ def check_buy_signals(symbol, data):
|
|||||||
latest = data.iloc[-1]
|
latest = data.iloc[-1]
|
||||||
prev = data.iloc[-2]
|
prev = data.iloc[-2]
|
||||||
|
|
||||||
# 볼린저 밴드 신호
|
# 볼린저 밴드 신호 (일봉 기준)
|
||||||
bb_signal = False
|
distance, lower_band, current_price = get_daily_bollinger_distance(data)
|
||||||
if isinstance(latest['Upper'], float):
|
|
||||||
upper_band = latest['Upper']
|
if distance is None:
|
||||||
lower_band = latest['Lower']
|
# 일봉 볼린저 계산이 불가능한 경우 기존 주기 데이터를 사용
|
||||||
current_price = latest['Close']
|
if isinstance(latest['Upper'], float):
|
||||||
else:
|
upper_band = latest['Upper']
|
||||||
upper_band = latest['Upper'].iloc[0]
|
lower_band = latest['Lower']
|
||||||
lower_band = latest['Lower'].iloc[0]
|
current_price = latest['Close']
|
||||||
current_price = latest['Close'].iloc[0]
|
else:
|
||||||
|
upper_band = latest['Upper'].iloc[0]
|
||||||
distance = (current_price - lower_band) / (upper_band - lower_band)
|
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
|
bb_signal = distance < BOLLINGER_THRESHOLD
|
||||||
|
|
||||||
# U자 반등 후 이전 고점 돌파 여부 계산 (BREAKOUT)
|
# U자 반등 후 이전 고점 돌파 여부 계산 (BREAKOUT)
|
||||||
|
|||||||
Reference in New Issue
Block a user