This commit is contained in:
dsyoon
2025-08-23 17:48:05 +09:00
parent 1543304536
commit 62771d068c
29 changed files with 232 additions and 4 deletions

View File

@@ -159,6 +159,7 @@ class Monitor:
# ------------- Strategy -------------
def buy_ticker(self, symbol: str, data: pd.DataFrame) -> bool:
try:
# 기존 로직 ---------------------------------------------------
#print('BUY: {}'.format(symbol))
#self.sendMsg('BUY: {}'.format(symbol))
@@ -217,6 +218,7 @@ class Monitor:
buy_amount = 20000
else:
buy_amount = 30000
# heikin_ashi 조건 제거 완료
if data['buy_signal'].iloc[-1] in ['movingaverage', 'deviation40', 'deviation240', 'deviation1440']:
if check_5_week_lowest:
@@ -240,6 +242,91 @@ class Monitor:
return False
return True
def sell_ticker(self, symbol: str, data: pd.DataFrame) -> bool:
try:
# 기존 로직 ---------------------------------------------------
#print('BUY: {}'.format(symbol))
#self.sendMsg('BUY: {}'.format(symbol))
check_5_week_lowest = False
# 5주봉이 20주봉이나 40주봉보다 아래에 있는지 체크
try:
# Convert hourly data to week-based rolling periods (5, 20, 40 weeks)
hours_in_week = 24 * 7 # 168 hours
period_5w = 5 * hours_in_week # 840 hours
period_20w = 20 * hours_in_week # 3,360 hours
period_40w = 40 * hours_in_week # 6,720 hours
if len(data) >= period_40w:
wma5 = data['Close'].rolling(window=period_5w).mean().iloc[-1]
wma20 = data['Close'].rolling(window=period_20w).mean().iloc[-1]
wma40 = data['Close'].rolling(window=period_40w).mean().iloc[-1]
# 5-week MA is the lowest among 5, 20, 40 week MAs
if (wma5 < wma20) and (wma5 < wma40):
check_5_week_lowest = True
except Exception:
# Ignore errors in MA calculation so as not to block trading logic
pass
current_time = datetime.now()
if data['sell_signal'].iloc[-1] == 'fall_6p':
if data['Close'].iloc[-1] > 100:
buy_amount = 500000
else:
buy_amount = 300000
if symbol in self.buy_cooldown and symbol in self.last_sell_signal:
if self.last_sell_signal[symbol] == 'fall_6p':
time_diff = current_time - self.buy_cooldown[symbol]
if time_diff.total_seconds() < 4000:
print(f"{symbol}: 매수 금지 중 (남은 시간: {600 - time_diff.total_seconds():.0f}초)")
return False
else:
if symbol in self.buy_cooldown:
time_diff = current_time - self.buy_cooldown[symbol]
if time_diff.total_seconds() < 1800:
print(f"{symbol}: 매수 금지 중 (남은 시간: {1800 - time_diff.total_seconds():.0f}초)")
return False
buy_amount = 5100
if data['sell_signal'].iloc[-1] == 'movingaverage':
buy_amount = 30000
elif data['sell_signal'].iloc[-1] == 'deviation40':
buy_amount = 50000
elif data['sell_signal'].iloc[-1] == 'deviation240':
buy_amount = 6000
elif data['sell_signal'].iloc[-1] == 'deviation1440':
if symbol in ['BONK', 'PEPE', 'TON']:
buy_amount = 20000
else:
buy_amount = 30000
# heikin_ashi 조건 제거 완료
if data['sell_signal'].iloc[-1] in ['movingaverage', 'deviation40', 'deviation240', 'deviation1440']:
if check_5_week_lowest:
buy_amount *= 4
_ = self.hts.buyCoinMarket(symbol, buy_amount)
if self.cooldown_file is not None:
# 최근 매수 신호를 함께 기록하여 [신규] 포맷으로 저장
try:
self.last_sell_signal[symbol] = str(data['sell_signal'].iloc[-1])
except Exception:
self.last_sell_signal[symbol] = ''
self.buy_cooldown[symbol] = current_time
self._save_buy_cooldown()
print(f"{KR_COINS[symbol]} ({symbol}) [{data['sell_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['sell_signal'].iloc[-1]))
except Exception as e:
print(f"Error buying {symbol}: {str(e)}")
return False
return True
def check_buy_point(self, symbol: str, data: pd.DataFrame, simulation: bool | None = None) -> pd.DataFrame:
data = data.copy()
data['buy_signal'] = ''