This commit is contained in:
dsyoon
2025-08-31 09:31:01 +09:00
parent 8e7dc9d1dd
commit 017989498a
6 changed files with 260 additions and 451 deletions

View File

@@ -225,11 +225,40 @@ class Monitor(HTS):
return data
# ------------- Strategy -------------
def buy_ticker_1h(self, symbol: str, data: pd.DataFrame) -> bool:
def buy_sell_ticker_1h(self, symbol: str, data: pd.DataFrame, balances=None, is_inverse: bool = False) -> bool:
try:
# 기존 로직 ---------------------------------------------------
#print('BUY: {}'.format(symbol))
#self.sendMsg('BUY: {}'.format(symbol))
# 신호 생성 및 최신 포인트 확인
data = self.annotate_signals(symbol, data)
if data['point'].iloc[-1] != 1:
return False
# 인버스 데이터: 매수 신호를 매도로 처리 (fall_6p, deviation40 만 허용)
if is_inverse:
# 허용된 인버스 매도 신호만 처리
last_signal = str(data['signal'].iloc[-1]) if 'signal' in data.columns else ''
if last_signal not in ['fall_6p', 'deviation40']:
return False
current_time = datetime.now()
available_balance = 0
try:
if balances and symbol in balances:
available_balance = float(balances[symbol].get('balance', 0))
except Exception:
available_balance = 0
if available_balance <= 0:
return False
sell_amount = available_balance * 0.7
_ = self.hts.sellCoinMarket(symbol, 0, sell_amount)
if self.cooldown_file is not None:
try:
self.last_signal[symbol] = str(data['signal'].iloc[-1])
except Exception:
self.last_signal[symbol] = ''
self.buy_cooldown.setdefault(symbol, {})['sell'] = {'datetime': current_time, 'signal': str(data['signal'].iloc[-1])}
self._save_buy_cooldown()
print(f"{KR_COINS[symbol]} ({symbol}) [{data['signal'].iloc[-1]} 매도], 현재가: {data['Close'].iloc[-1]:.4f}")
self.sendMsg("[KRW-COIN]\n" + f"• 매도 [COIN] {KR_COINS[symbol]} ({symbol}): {data['signal'].iloc[-1]} ({''}{data['Close'].iloc[-1]:.4f})")
return True
check_5_week_lowest = False
@@ -313,44 +342,7 @@ class Monitor(HTS):
return False
return True
def sell_ticker_1h(self, symbol: str, data: pd.DataFrame, balances) -> bool:
"""Dev40(Deviation40) 매도 조건을 만족할 때만 매도 실행"""
try:
# 최신 캔들의 시그널이 Dev40이 아니면 매도하지 않음
if data['signal'].iloc[-1] != 'deviation40':
return False
current_time = datetime.now()
# 최근 Dev40 매도로부터 20분(1200초) 쿨다운 적용
last_sell_dt = self.buy_cooldown.get(symbol, {}).get('sell', {}).get('datetime')
if last_sell_dt and self.last_signal.get(symbol) == 'deviation40':
time_diff = current_time - last_sell_dt
if time_diff.total_seconds() < 1200:
remain = 1200 - time_diff.total_seconds()
print(f"{symbol}: 매도 금지 중 (남은 시간: {remain:.0f}초)")
return False
# 매도 수량/금액 산정 (예: 50,000 KRW 상당)
sell_amount = balances[symbol]['balance'] * 0.7 # KRW 기준 매도 총액 혹은 수량 설정
# 실제 매도 실행 (HTS API)
_ = self.hts.sellCoinMarket(symbol, 0, sell_amount) # market 매도 (price 파라미터 미사용)
# 쿨다운 및 로그 저장
if self.cooldown_file is not None:
self.last_signal[symbol] = 'deviation40'
self.buy_cooldown.setdefault(symbol, {})['sell'] = {'datetime': current_time, 'signal': 'deviation40'}
self._save_buy_cooldown()
print(f"{KR_COINS[symbol]} ({symbol}) [Dev40 매도], 현재가: {data['Close'].iloc[-1]:.4f}, 20분간 매도 금지 시작")
self.sendMsg("[KRW-COIN]" + "\n" + self.format_message('COIN', symbol, KR_COINS[symbol], data['Close'].iloc[-1], 'Dev40 매도'))
except Exception as e:
print(f"Error selling {symbol}: {str(e)}")
return False
return True
def check_point(self, symbol: str, data: pd.DataFrame, simulation: bool | None = None) -> pd.DataFrame:
def annotate_signals(self, symbol: str, data: pd.DataFrame, simulation: bool | None = None) -> pd.DataFrame:
data = data.copy()
data['signal'] = ''
data['point'] = 0
@@ -417,6 +409,27 @@ class Monitor(HTS):
data.at[data.index[-1], 'signal'] = 'deviation1440'
data.at[data.index[-1], 'point'] = 1
# Deviation720 상향 돌파 매수 (92, 93)
try:
prev_d720 = data['Deviation720'].iloc[i - 1]
curr_d720 = data['Deviation720'].iloc[i]
# 92 상향 돌파
if prev_d720 < 92 and curr_d720 >= 92:
data.at[data.index[i], 'signal'] = 'Deviation720'
data.at[data.index[i], 'point'] = 1
if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'signal'] = 'Deviation720'
data.at[data.index[-1], 'point'] = 1
# 93 상향 돌파
if prev_d720 < 93 and curr_d720 >= 93:
data.at[data.index[i], 'signal'] = 'Deviation720'
data.at[data.index[i], 'point'] = 1
if not simulation and data['point'][-3:].sum() > 0:
data.at[data.index[-1], 'signal'] = 'Deviation720'
data.at[data.index[-1], 'point'] = 1
except Exception:
pass
try:
prev_low = data['Low'].iloc[i - 1]
curr_close = data['Close'].iloc[i]