This commit is contained in:
dsyoon
2025-08-23 18:20:49 +09:00
parent 865a5c8680
commit 6cb939d690
31 changed files with 235 additions and 235 deletions

View File

@@ -20,5 +20,5 @@
특정 월의 데이터를 가져오기 위한 코드를 추가 작성하지 마세요. 데이터는 현재 전체 기간을 이용해서 기술적 분석을 하고 저점을 찾으세요. 특정 월의 데이터를 가져오기 위한 코드를 추가 작성하지 마세요. 데이터는 현재 전체 기간을 이용해서 기술적 분석을 하고 저점을 찾으세요.
calculate_technical_indicators 함수에 기술적 분석들을 작성하세요 calculate_technical_indicators 함수에 기술적 분석들을 작성하세요
check_buy_point 함수에서 매수 여부를 판단하세요. check_point 함수에서 매수 여부를 판단하세요.
저점 매수는 구분지 buy_lower를 사용하세요. 저점 매수는 구분지 buy_lower를 사용하세요.

View File

@@ -18,13 +18,13 @@ import os
class Monitor: class Monitor:
"""자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스"""
last_buy_signal = None last_signal = None
cooldown_file = None cooldown_file = None
def __init__(self, cooldown_file='coins_buy_time.json') -> None: def __init__(self, cooldown_file='coins_buy_time.json') -> None:
self.hts = HTS() self.hts = HTS()
# 최근 매수 신호 저장용(파일은 [신규] 포맷으로 저장) # 최근 매수 신호 저장용(파일은 [신규] 포맷으로 저장)
self.last_buy_signal: dict[str, str] = {} self.last_signal: dict[str, str] = {}
if cooldown_file is not None: if cooldown_file is not None:
self.cooldown_file = cooldown_file self.cooldown_file = cooldown_file
self.buy_cooldown = self._load_buy_cooldown() self.buy_cooldown = self._load_buy_cooldown()
@@ -45,16 +45,16 @@ class Monitor:
except Exception: except Exception:
continue continue
elif isinstance(value, dict): elif isinstance(value, dict):
# [신규] 포맷: "SYMBOL": {"datetime": "...", "buy_signal": "..."} # [신규] 포맷: "SYMBOL": {"datetime": "...", "signal": "..."}
dt_str = value.get('datetime') dt_str = value.get('datetime')
if isinstance(dt_str, str): if isinstance(dt_str, str):
try: try:
cooldown[symbol] = datetime.fromisoformat(dt_str) cooldown[symbol] = datetime.fromisoformat(dt_str)
except Exception: except Exception:
pass pass
buy_signal = value.get('buy_signal', '') signal = value.get('signal', '')
if isinstance(buy_signal, str): if isinstance(signal, str):
self.last_buy_signal[symbol] = buy_signal self.last_signal[symbol] = signal
return cooldown return cooldown
except Exception as e: except Exception as e:
print(f"Error loading cooldown data: {e}") print(f"Error loading cooldown data: {e}")
@@ -68,7 +68,7 @@ class Monitor:
for symbol, dt in self.buy_cooldown.items(): for symbol, dt in self.buy_cooldown.items():
data[symbol] = { data[symbol] = {
'datetime': dt.isoformat(), 'datetime': dt.isoformat(),
'buy_signal': self.last_buy_signal.get(symbol, '') 'signal': self.last_signal.get(symbol, '')
} }
with open(self.cooldown_file, 'w', encoding='utf-8') as f: with open(self.cooldown_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2) json.dump(data, f, ensure_ascii=False, indent=2)
@@ -226,14 +226,14 @@ class Monitor:
pass pass
current_time = datetime.now() current_time = datetime.now()
if data['buy_signal'].iloc[-1] == 'fall_6p': if data['signal'].iloc[-1] == 'fall_6p':
if data['Close'].iloc[-1] > 100: if data['Close'].iloc[-1] > 100:
buy_amount = 500000 buy_amount = 500000
else: else:
buy_amount = 300000 buy_amount = 300000
if symbol in self.buy_cooldown and symbol in self.last_buy_signal: if symbol in self.buy_cooldown and symbol in self.last_signal:
if self.last_buy_signal[symbol] == 'fall_6p': if self.last_signal[symbol] == 'fall_6p':
time_diff = current_time - self.buy_cooldown[symbol] time_diff = current_time - self.buy_cooldown[symbol]
if time_diff.total_seconds() < 4000: if time_diff.total_seconds() < 4000:
print(f"{symbol}: 매수 금지 중 (남은 시간: {600 - time_diff.total_seconds():.0f}초)") print(f"{symbol}: 매수 금지 중 (남은 시간: {600 - time_diff.total_seconds():.0f}초)")
@@ -246,20 +246,20 @@ class Monitor:
return False return False
buy_amount = 5100 buy_amount = 5100
if data['buy_signal'].iloc[-1] == 'movingaverage': if data['signal'].iloc[-1] == 'movingaverage':
buy_amount = 30000 buy_amount = 30000
elif data['buy_signal'].iloc[-1] == 'deviation40': elif data['signal'].iloc[-1] == 'deviation40':
buy_amount = 50000 buy_amount = 50000
elif data['buy_signal'].iloc[-1] == 'deviation240': elif data['signal'].iloc[-1] == 'deviation240':
buy_amount = 6000 buy_amount = 6000
elif data['buy_signal'].iloc[-1] == 'deviation1440': elif data['signal'].iloc[-1] == 'deviation1440':
if symbol in ['BONK', 'PEPE', 'TON']: if symbol in ['BONK', 'PEPE', 'TON']:
buy_amount = 20000 buy_amount = 20000
else: else:
buy_amount = 30000 buy_amount = 30000
# heikin_ashi 조건 제거 완료 # heikin_ashi 조건 제거 완료
if data['buy_signal'].iloc[-1] in ['movingaverage', 'deviation40', 'deviation240', 'deviation1440']: if data['signal'].iloc[-1] in ['movingaverage', 'deviation40', 'deviation240', 'deviation1440']:
if check_5_week_lowest: if check_5_week_lowest:
buy_amount *= 4 buy_amount *= 4
@@ -268,14 +268,14 @@ class Monitor:
if self.cooldown_file is not None: if self.cooldown_file is not None:
# 최근 매수 신호를 함께 기록하여 [신규] 포맷으로 저장 # 최근 매수 신호를 함께 기록하여 [신규] 포맷으로 저장
try: try:
self.last_buy_signal[symbol] = str(data['buy_signal'].iloc[-1]) self.last_signal[symbol] = str(data['signal'].iloc[-1])
except Exception: except Exception:
self.last_buy_signal[symbol] = '' self.last_signal[symbol] = ''
self.buy_cooldown[symbol] = current_time self.buy_cooldown[symbol] = current_time
self._save_buy_cooldown() self._save_buy_cooldown()
print(f"{KR_COINS[symbol]} ({symbol}) [{data['buy_signal'].iloc[-1]}], 현재가: {data['Close'].iloc[-1]:.4f}, 20분간 매수 금지 시작") print(f"{KR_COINS[symbol]} ({symbol}) [{data['signal'].iloc[-1]}], 현재가: {data['Close'].iloc[-1]:.4f}, 20분간 매수 금지 시작")
self.sendMsg("[KRW-COIN]" + "\n" + self.format_message('COIN', symbol, KR_COINS[symbol], data['Close'].iloc[-1], data['buy_signal'].iloc[-1])) self.sendMsg("[KRW-COIN]" + "\n" + self.format_message('COIN', symbol, KR_COINS[symbol], data['Close'].iloc[-1], data['signal'].iloc[-1]))
except Exception as e: except Exception as e:
print(f"Error buying {symbol}: {str(e)}") print(f"Error buying {symbol}: {str(e)}")
return False return False
@@ -366,72 +366,72 @@ class Monitor:
return False return False
return True return True
def check_buy_point(self, symbol: str, data: pd.DataFrame, simulation: bool | None = None) -> pd.DataFrame: def check_point(self, symbol: str, data: pd.DataFrame, simulation: bool | None = None) -> pd.DataFrame:
data = data.copy() data = data.copy()
data['buy_signal'] = '' data['signal'] = ''
data['buy_point'] = 0 data['point'] = 0
if data['buy_point'].iloc[-1] != 1: if data['point'].iloc[-1] != 1:
for i in range(1, len(data)): for i in range(1, len(data)):
if all(data[f'MA{n}'].iloc[i] < data['MA720'].iloc[i] for n in [5, 20, 40, 120, 200, 240]) and \ if all(data[f'MA{n}'].iloc[i] < data['MA720'].iloc[i] for n in [5, 20, 40, 120, 200, 240]) and \
all(data[f'MA{n}'].iloc[i] > data[f'MA{n}'].iloc[i - 1] for n in [5, 20, 40, 120, 200, 240]) and \ all(data[f'MA{n}'].iloc[i] > data[f'MA{n}'].iloc[i - 1] for n in [5, 20, 40, 120, 200, 240]) and \
data['MA720'].iloc[i] < data['MA1440'].iloc[i]: data['MA720'].iloc[i] < data['MA1440'].iloc[i]:
data.at[data.index[i], 'buy_signal'] = 'movingaverage' data.at[data.index[i], 'signal'] = 'movingaverage'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'movingaverage' data.at[data.index[-1], 'signal'] = 'movingaverage'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
if data['Deviation40'].iloc[i - 1] < data['Deviation40'].iloc[i] and data['Deviation40'].iloc[i - 1] <= 90: if data['Deviation40'].iloc[i - 1] < data['Deviation40'].iloc[i] and data['Deviation40'].iloc[i - 1] <= 90:
data.at[data.index[i], 'buy_signal'] = 'deviation40' data.at[data.index[i], 'signal'] = 'deviation40'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation40' data.at[data.index[-1], 'signal'] = 'deviation40'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
if symbol not in ['BONK']: if symbol not in ['BONK']:
if symbol in ['TRX']: if symbol in ['TRX']:
if data['Deviation240'].iloc[i - 1] < data['Deviation240'].iloc[i] and data['Deviation240'].iloc[i - 1] <= 98: if data['Deviation240'].iloc[i - 1] < data['Deviation240'].iloc[i] and data['Deviation240'].iloc[i - 1] <= 98:
data.at[data.index[i], 'buy_signal'] = 'deviation240' data.at[data.index[i], 'signal'] = 'deviation240'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation240' data.at[data.index[-1], 'signal'] = 'deviation240'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
else: else:
if data['Deviation240'].iloc[i - 1] < data['Deviation240'].iloc[i] and data['Deviation240'].iloc[i - 1] <= 90: if data['Deviation240'].iloc[i - 1] < data['Deviation240'].iloc[i] and data['Deviation240'].iloc[i - 1] <= 90:
data.at[data.index[i], 'buy_signal'] = 'deviation240' data.at[data.index[i], 'signal'] = 'deviation240'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation240' data.at[data.index[-1], 'signal'] = 'deviation240'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
if symbol in ['TON']: if symbol in ['TON']:
if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 89: if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 89:
data.at[data.index[i], 'buy_signal'] = 'deviation1440' data.at[data.index[i], 'signal'] = 'deviation1440'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation1440' data.at[data.index[-1], 'signal'] = 'deviation1440'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
elif symbol in ['XRP']: elif symbol in ['XRP']:
if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 90: if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 90:
data.at[data.index[i], 'buy_signal'] = 'deviation1440' data.at[data.index[i], 'signal'] = 'deviation1440'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation1440' data.at[data.index[-1], 'signal'] = 'deviation1440'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
elif symbol in ['BONK']: elif symbol in ['BONK']:
if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 76: if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 76:
data.at[data.index[i], 'buy_signal'] = 'deviation1440' data.at[data.index[i], 'signal'] = 'deviation1440'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation1440' data.at[data.index[-1], 'signal'] = 'deviation1440'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
else: else:
if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 80: if data['Deviation1440'].iloc[i - 1] < data['Deviation1440'].iloc[i] and data['Deviation1440'].iloc[i - 1] <= 80:
data.at[data.index[i], 'buy_signal'] = 'deviation1440' data.at[data.index[i], 'signal'] = 'deviation1440'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'deviation1440' data.at[data.index[-1], 'signal'] = 'deviation1440'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
try: try:
prev_low = data['Low'].iloc[i - 1] prev_low = data['Low'].iloc[i - 1]
@@ -440,18 +440,18 @@ class Monitor:
cond_close_drop = curr_close <= prev_low * 0.94 cond_close_drop = curr_close <= prev_low * 0.94
cond_low_drop = curr_low <= prev_low * 0.94 cond_low_drop = curr_low <= prev_low * 0.94
if cond_close_drop or cond_low_drop: if cond_close_drop or cond_low_drop:
data.at[data.index[i], 'buy_signal'] = 'fall_6p' data.at[data.index[i], 'signal'] = 'fall_6p'
data.at[data.index[i], 'buy_point'] = 1 data.at[data.index[i], 'point'] = 1
if not simulation and data['buy_point'][-3:].sum() > 0: if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'buy_signal'] = 'fall_6p' data.at[data.index[-1], 'signal'] = 'fall_6p'
data.at[data.index[-1], 'buy_point'] = 1 data.at[data.index[-1], 'point'] = 1
except Exception: except Exception:
pass pass
return data return data
# ------------- Formatting ------------- # ------------- Formatting -------------
def format_message(self, market_type: str, symbol: str, symbol_name: str, close: float, buy_signal: str) -> str: def format_message(self, market_type: str, symbol: str, symbol_name: str, close: float, signal: str) -> str:
message = f"• 매수 [{market_type}] {symbol_name} ({symbol}): {buy_signal} " message = f"• 매수 [{market_type}] {symbol_name} ({symbol}): {signal} "
message += f"({'$' if market_type == 'US' else ''}{close:.4f})" message += f"({'$' if market_type == 'US' else ''}{close:.4f})"
return message return message

View File

@@ -18,17 +18,17 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData= self.inverse_data(data) inverseData= self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
continue continue
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
continue continue
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
continue continue
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -18,16 +18,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData= self.inverse_data(data) inverseData= self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
continue continue
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
continue continue
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
continue continue
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -18,16 +18,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData= self.inverse_data(data) inverseData= self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
continue continue
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
continue continue
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
continue continue
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -23,16 +23,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -17,16 +17,16 @@ class MonitorCoin (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
inverseData = self.inverse_data(data) inverseData = self.inverse_data(data)
recent_inverseData = self.check_buy_point(symbol, inverseData) recent_inverseData = self.check_point(symbol, inverseData)
if recent_inverseData['sell_point'].iloc[-1] != 1: if recent_inverseData['point'].iloc[-1] != 1:
return return
sell_success = self.sell_ticker(symbol, recent_inverseData) sell_success = self.sell_ticker(symbol, recent_inverseData)
if not sell_success: if not sell_success:
return return
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
return return
buy_success = self.buy_ticker(symbol, recent_data) buy_success = self.buy_ticker(symbol, recent_data)
if not buy_success: if not buy_success:

View File

@@ -47,8 +47,8 @@ class MonitorStock (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
continue continue
print(f" - {US_STOCKS[symbol]} ({symbol}): {recent_data['Close'].iloc[-1]:.2f}") print(f" - {US_STOCKS[symbol]} ({symbol}): {recent_data['Close'].iloc[-1]:.2f}")
message_list.append( message_list.append(
@@ -73,8 +73,8 @@ class MonitorStock (Monitor):
if data is not None and not data.empty: if data is not None and not data.empty:
try: try:
data = self.calculate_technical_indicators(data) data = self.calculate_technical_indicators(data)
recent_data = self.check_buy_point(symbol, data) recent_data = self.check_point(symbol, data)
if recent_data['buy_point'].iloc[-1] != 1: if recent_data['point'].iloc[-1] != 1:
continue continue
print(f" - {KR_ETFS[symbol]} ({symbol}): {recent_data['Close'].iloc[-1]:.2f}") print(f" - {KR_ETFS[symbol]} ({symbol}): {recent_data['Close'].iloc[-1]:.2f}")
message_list.append( message_list.append(

View File

@@ -24,7 +24,7 @@ class Simulation:
if len(data) < 7: if len(data) < 7:
return None return None
current_data = data.iloc[-1] current_data = data.iloc[-1]
if current_data.get('buy_point', 0) == 1: if current_data.get('point', 0) == 1:
return { return {
'alert': True, 'alert': True,
'details': f"매수신호: {current_data.get('buy_signal', 'unknown')}" 'details': f"매수신호: {current_data.get('buy_signal', 'unknown')}"
@@ -51,7 +51,7 @@ class Simulation:
def analyze_bottom_period(self, symbol: str, interval_minutes: int, days: int = 90): def analyze_bottom_period(self, symbol: str, interval_minutes: int, days: int = 90):
data = self.fetch_price_history(symbol, interval_minutes, days) data = self.fetch_price_history(symbol, interval_minutes, days)
data = self.monitor.calculate_technical_indicators(data) data = self.monitor.calculate_technical_indicators(data)
data = self.monitor.check_buy_point(symbol, data, simulation=True) data = self.monitor.check_point(symbol, data, simulation=True)
print(f"데이터 기간: {data.index[0]} ~ {data.index[-1]}") print(f"데이터 기간: {data.index[0]} ~ {data.index[-1]}")
print(f"총 데이터 수: {len(data)}") print(f"총 데이터 수: {len(data)}")
bottom_start = pd.Timestamp('2025-06-22') bottom_start = pd.Timestamp('2025-06-22')
@@ -88,7 +88,7 @@ class Simulation:
print(f"가격: {actual_bottom_price:.4f}") print(f"가격: {actual_bottom_price:.4f}")
print(f"볼린저 하단 대비: {((actual_bottom_price - bottom_data.loc[actual_bottom_idx, 'Lower']) / bottom_data.loc[actual_bottom_idx, 'Lower'] * 100):.2f}%") print(f"볼린저 하단 대비: {((actual_bottom_price - bottom_data.loc[actual_bottom_idx, 'Lower']) / bottom_data.loc[actual_bottom_idx, 'Lower'] * 100):.2f}%")
print(f"\n=== 매수 신호 분석 ===") print(f"\n=== 매수 신호 분석 ===")
bottom_alerts = bottom_data[bottom_data['buy_point'] == 1] bottom_alerts = bottom_data[bottom_data['point'] == 1]
alerts = [(idx, row['Close']) for idx, row in bottom_alerts.iterrows()] alerts = [(idx, row['Close']) for idx, row in bottom_alerts.iterrows()]
print(f"저점 기간 매수 신호 수: {len(alerts)}") print(f"저점 기간 매수 신호 수: {len(alerts)}")
if alerts: if alerts:
@@ -100,18 +100,18 @@ class Simulation:
def run_simulation(self, symbol: str, interval_minutes: int, days: int = 30): def run_simulation(self, symbol: str, interval_minutes: int, days: int = 30):
data = self.fetch_price_history(symbol, interval_minutes) data = self.fetch_price_history(symbol, interval_minutes)
data = self.monitor.calculate_technical_indicators(data) data = self.monitor.calculate_technical_indicators(data)
data = self.monitor.check_buy_point(symbol, data, simulation=True) data = self.monitor.check_point(symbol, data, simulation=True)
print(f"데이터 기간: {data.index[0]} ~ {data.index[-1]}") print(f"데이터 기간: {data.index[0]} ~ {data.index[-1]}")
print(f"총 데이터 수: {len(data)}") print(f"총 데이터 수: {len(data)}")
alerts = [] alerts = []
for i in range(len(data)): for i in range(len(data)):
if data['buy_point'].iloc[i] == 1: if data['point'].iloc[i] == 1:
alerts.append((data.index[i], data['Close'].iloc[i])) alerts.append((data.index[i], data['Close'].iloc[i]))
print(f"\n총 매수 신호 수: {len(alerts)}") print(f"\n총 매수 신호 수: {len(alerts)}")
ma_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'movingaverage')]) ma_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'movingaverage')])
dev40_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation40')]) dev40_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation40')])
dev240_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation240')]) dev240_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation240')])
dev1440_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation1440')]) dev1440_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation1440')])
print(f" - MA 신호: {ma_signals}") print(f" - MA 신호: {ma_signals}")
print(f" - Dev40 신호: {dev40_signals}") print(f" - Dev40 신호: {dev40_signals}")
print(f" - Dev240 신호: {dev240_signals}") print(f" - Dev240 신호: {dev240_signals}")
@@ -236,70 +236,70 @@ class Simulation:
# 매수 포인트를 신호 유형별로 다르게 표시 (수직선 포함) # 매수 포인트를 신호 유형별로 다르게 표시 (수직선 포함)
# 이동평균선 기반 매수 포인트 # 이동평균선 기반 매수 포인트
ma_buy_points = data[(data['buy_point'] == 1) & (data['buy_signal'] == 'movingaverage')] ma_points = data[(data['point'] == 1) & (data['buy_signal'] == 'movingaverage')]
scatter_ma_buy_points = None scatter_ma_points = None
if len(ma_buy_points) > 0: if len(ma_points) > 0:
scatter_ma_buy_points = ax1.scatter(ma_buy_points.index, ma_buy_points['Close'], color='red', s=150, zorder=10, label='MA 매수 포인트', marker='o') scatter_ma_points = ax1.scatter(ma_points.index, ma_points['Close'], color='red', s=150, zorder=10, label='MA 매수 포인트', marker='o')
for time in ma_buy_points.index: for time in ma_points.index:
ax1.axvline(x=time, color='red', linestyle='-', alpha=0.5, linewidth=1) ax1.axvline(x=time, color='red', linestyle='-', alpha=0.5, linewidth=1)
# Deviation40 기반 매수 포인트 # Deviation40 기반 매수 포인트
dev40_buy_points = data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation40')] dev40_points = data[(data['point'] == 1) & (data['buy_signal'] == 'deviation40')]
scatter_dev40_buy_points = None scatter_dev40_points = None
if len(dev40_buy_points) > 0: if len(dev40_points) > 0:
scatter_dev40_buy_points = ax1.scatter(dev40_buy_points.index, dev40_buy_points['Close'], scatter_dev40_points = ax1.scatter(dev40_points.index, dev40_points['Close'],
facecolors='none', edgecolors='red', linestyle='--', facecolors='none', edgecolors='red', linestyle='--',
linewidth=2, s=200, zorder=10, label='Dev40 매수 포인트') linewidth=2, s=200, zorder=10, label='Dev40 매수 포인트')
for time in dev40_buy_points.index: for time in dev40_points.index:
ax1.axvline(x=time, color='red', linestyle='--', alpha=0.5, linewidth=1) ax1.axvline(x=time, color='red', linestyle='--', alpha=0.5, linewidth=1)
# Deviation240 기반 매수 포인트 # Deviation240 기반 매수 포인트
dev240_buy_points = data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation240')] dev240_points = data[(data['point'] == 1) & (data['buy_signal'] == 'deviation240')]
scatter_dev240_buy_points = None scatter_dev240_points = None
if len(dev240_buy_points) > 0: if len(dev240_points) > 0:
scatter_dev240_buy_points = ax1.scatter(dev240_buy_points.index, dev240_buy_points['Close'], scatter_dev240_points = ax1.scatter(dev240_points.index, dev240_points['Close'],
facecolors='none', edgecolors='blue', linestyle='--', facecolors='none', edgecolors='blue', linestyle='--',
linewidth=2, s=200, zorder=10, label='Dev240 매수 포인트') linewidth=2, s=200, zorder=10, label='Dev240 매수 포인트')
for time in dev240_buy_points.index: for time in dev240_points.index:
ax1.axvline(x=time, color='blue', linestyle='--', alpha=0.5, linewidth=1) ax1.axvline(x=time, color='blue', linestyle='--', alpha=0.5, linewidth=1)
# Deviation1440 기반 매수 포인트 # Deviation1440 기반 매수 포인트
dev1440_buy_points = data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation1440')] dev1440_points = data[(data['point'] == 1) & (data['buy_signal'] == 'deviation1440')]
scatter_dev1440_buy_points = None scatter_dev1440_points = None
if len(dev1440_buy_points) > 0: if len(dev1440_points) > 0:
scatter_dev1440_buy_points = ax1.scatter(dev1440_buy_points.index, dev1440_buy_points['Close'], scatter_dev1440_points = ax1.scatter(dev1440_points.index, dev1440_points['Close'],
facecolors='none', edgecolors='purple', linestyle='--', facecolors='none', edgecolors='purple', linestyle='--',
linewidth=2, s=200, zorder=10, label='Dev1440 매수 포인트') linewidth=2, s=200, zorder=10, label='Dev1440 매수 포인트')
for time in dev1440_buy_points.index: for time in dev1440_points.index:
ax1.axvline(x=time, color='purple', linestyle='--', alpha=0.5, linewidth=1) ax1.axvline(x=time, color='purple', linestyle='--', alpha=0.5, linewidth=1)
# 마우스 오버 기능 추가 (이동평균선 매수 포인트) # 마우스 오버 기능 추가 (이동평균선 매수 포인트)
if scatter_ma_buy_points is not None: if scatter_ma_points is not None:
cursor = mplcursors.cursor(scatter_ma_buy_points, hover=True) cursor = mplcursors.cursor(scatter_ma_points, hover=True)
cursor.connect("add", lambda sel: sel.annotation.set_text( cursor.connect("add", lambda sel: sel.annotation.set_text(
f'MA 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}' f'MA 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}'
)) ))
cursor.connect("remove", lambda sel: sel.annotation.set_visible(False)) cursor.connect("remove", lambda sel: sel.annotation.set_visible(False))
# 마우스 오버 기능 추가 (Deviation40 매수 포인트) # 마우스 오버 기능 추가 (Deviation40 매수 포인트)
if scatter_dev40_buy_points is not None: if scatter_dev40_points is not None:
cursor_dev40 = mplcursors.cursor(scatter_dev40_buy_points, hover=True) cursor_dev40 = mplcursors.cursor(scatter_dev40_points, hover=True)
cursor_dev40.connect("add", lambda sel: sel.annotation.set_text( cursor_dev40.connect("add", lambda sel: sel.annotation.set_text(
f'Dev40 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}' f'Dev40 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}'
)) ))
cursor_dev40.connect("remove", lambda sel: sel.annotation.set_visible(False)) cursor_dev40.connect("remove", lambda sel: sel.annotation.set_visible(False))
# 마우스 오버 기능 추가 (Deviation240 매수 포인트) # 마우스 오버 기능 추가 (Deviation240 매수 포인트)
if scatter_dev240_buy_points is not None: if scatter_dev240_points is not None:
cursor_dev240 = mplcursors.cursor(scatter_dev240_buy_points, hover=True) cursor_dev240 = mplcursors.cursor(scatter_dev240_points, hover=True)
cursor_dev240.connect("add", lambda sel: sel.annotation.set_text( cursor_dev240.connect("add", lambda sel: sel.annotation.set_text(
f'Dev240 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}' f'Dev240 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}'
)) ))
cursor_dev240.connect("remove", lambda sel: sel.annotation.set_visible(False)) cursor_dev240.connect("remove", lambda sel: sel.annotation.set_visible(False))
# 마우스 오버 기능 추가 (Deviation1440 매수 포인트) # 마우스 오버 기능 추가 (Deviation1440 매수 포인트)
if scatter_dev1440_buy_points is not None: if scatter_dev1440_points is not None:
cursor_dev1440 = mplcursors.cursor(scatter_dev1440_buy_points, hover=True) cursor_dev1440 = mplcursors.cursor(scatter_dev1440_points, hover=True)
cursor_dev1440.connect("add", lambda sel: sel.annotation.set_text( cursor_dev1440.connect("add", lambda sel: sel.annotation.set_text(
f'Dev1440 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}' f'Dev1440 매수신호\n날짜: {matplotlib.dates.num2date(sel.target[0]).replace(tzinfo=None).strftime("%Y-%m-%d %H:%M")}\n가격: {sel.target[1]:.2f}'
)) ))
@@ -340,14 +340,14 @@ class Simulation:
plot_lines = [line_close, line_ma5, line_ma20, line_ma40, line_ma120, plot_lines = [line_close, line_ma5, line_ma20, line_ma40, line_ma120,
line_ma200, line_ma240, line_ma720, line_ma1440, line_ma200, line_ma240, line_ma720, line_ma1440,
line_upper, line_lower] line_upper, line_lower]
if scatter_ma_buy_points is not None: if scatter_ma_points is not None:
plot_lines.append(scatter_ma_buy_points) plot_lines.append(scatter_ma_points)
if scatter_dev40_buy_points is not None: if scatter_dev40_points is not None:
plot_lines.append(scatter_dev40_buy_points) plot_lines.append(scatter_dev40_points)
if scatter_dev240_buy_points is not None: if scatter_dev240_points is not None:
plot_lines.append(scatter_dev240_buy_points) plot_lines.append(scatter_dev240_points)
if scatter_dev1440_buy_points is not None: if scatter_dev1440_points is not None:
plot_lines.append(scatter_dev1440_buy_points) plot_lines.append(scatter_dev1440_points)
for leg_handle, orig in zip(legend_handles[:len(plot_lines)], plot_lines): for leg_handle, orig in zip(legend_handles[:len(plot_lines)], plot_lines):
leg_handle.set_picker(True) leg_handle.set_picker(True)
@@ -436,7 +436,7 @@ class Simulation:
plt.tight_layout() plt.tight_layout()
print("그래프를 표시합니다...") print("그래프를 표시합니다...")
print(f"매수 포인트 수: MA={len(ma_buy_points)}, Dev40={len(dev40_buy_points)}, Dev240={len(dev240_buy_points)}") print(f"매수 포인트 수: MA={len(ma_points)}, Dev40={len(dev40_points)}, Dev240={len(dev240_points)}")
# -------- 확대/축소 및 이동 기능 -------- # -------- 확대/축소 및 이동 기능 --------
press = {} press = {}
@@ -502,12 +502,12 @@ if __name__ == "__main__":
else: else:
data = sim.fetch_price_history(symbol, interval, days) data = sim.fetch_price_history(symbol, interval, days)
data = sim.monitor.calculate_technical_indicators(data) data = sim.monitor.calculate_technical_indicators(data)
data = sim.monitor.check_buy_point(symbol, data, simulation=True) data = sim.monitor.check_point(symbol, data, simulation=True)
total_buy_signals = len(data[data['buy_point'] == 1]) total_buy_signals = len(data[data['point'] == 1])
ma_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'movingaverage')]) ma_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'movingaverage')])
dev40_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation40')]) dev40_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation40')])
dev240_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation240')]) dev240_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation240')])
dev1440_signals = len(data[(data['buy_point'] == 1) & (data['buy_signal'] == 'deviation1440')]) dev1440_signals = len(data[(data['point'] == 1) & (data['buy_signal'] == 'deviation1440')])
print(f"총 매수 신호: {total_buy_signals}") print(f"총 매수 신호: {total_buy_signals}")
print(f" - MA 신호: {ma_signals}") print(f" - MA 신호: {ma_signals}")
print(f" - Dev40 신호: {dev40_signals}") print(f" - Dev40 신호: {dev40_signals}")