v0.5.1: RSI + Bollinger Bands HYBRID - Confidence filter (58%+ Win-Rate target)

This commit is contained in:
Marc Blatter 2026-07-27 16:43:35 +02:00
parent c23a00060e
commit 49af729df1
2 changed files with 61 additions and 22 deletions

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Trading Bot v0.5 - Bollinger Bands Entry Signals (60%+ Win-Rate target)"""
"""Trading Bot v0.5.1 - RSI + Bollinger Bands HYBRID (Confidence Filter)"""
import os, json, time, logging, sqlite3
from datetime import datetime
from dotenv import load_dotenv
@ -25,8 +25,10 @@ STOP_LOSS_PCT = -0.008
CYCLE_SEC = 60
BB_PERIOD = 20
BB_STD_DEV = 2.0
RSI_PERIOD = 14
RSI_THRESHOLD = 35
class TradingBotV05:
class TradingBotV051:
def __init__(self):
self.client = Client(API_KEY, API_SECRET)
self.price_history = {sym: [] for sym in SYMBOLS}
@ -57,7 +59,29 @@ class TradingBotV05:
except Exception as e:
logger.warning(f"Recovery failed: {e}")
logger.info("[v0.5 INIT] Bollinger Bands Entry Signals (60%+ WR target)")
logger.info("[v0.5.1 INIT] RSI + Bollinger Bands HYBRID (Confidence Filter)")
def calculate_rsi(self, prices):
"""Calculate RSI (14-period standard)"""
if len(prices) < RSI_PERIOD + 1:
return None
recent = prices[-RSI_PERIOD-1:]
deltas = [recent[i+1] - recent[i] for i in range(len(recent)-1)]
gains = [d if d > 0 else 0 for d in deltas]
losses = [abs(d) if d < 0 else 0 for d in deltas]
avg_gain = sum(gains) / RSI_PERIOD
avg_loss = sum(losses) / RSI_PERIOD
if avg_loss == 0:
return 100.0 if avg_gain > 0 else 0.0
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return rsi
def calculate_bollinger_bands(self, prices):
"""Calculate 20-EMA +/- 2*StdDev"""
@ -81,9 +105,13 @@ class TradingBotV05:
return ema, upper_band, lower_band
def is_bollinger_breakout(self, symbol):
"""Buy when price rebounds from lower band (crosses from below to above)"""
if len(self.price_history[symbol]) < BB_PERIOD + 1:
def is_hybrid_buy_signal(self, symbol):
"""
HYBRID Signal: Buy ONLY when BOTH conditions met:
1. Price rebounds from lower Bollinger Band (BB Breakout)
2. RSI < 35 (Oversolod confirmation)
"""
if len(self.price_history[symbol]) < max(BB_PERIOD + 1, RSI_PERIOD + 1):
return False
prices = self.price_history[symbol]
@ -95,13 +123,24 @@ class TradingBotV05:
current_price = prices[-1]
prev_price = prices[-2]
# Signal: Price was below lower band, now above lower band
breakout = (prev_price < lower and current_price > lower)
# Signal 1: Bollinger Breakout
bb_breakout = (prev_price < lower and current_price > lower)
if breakout:
logger.info(f"[SIGNAL-BB] {symbol} Bollinger Breakout (EMA={ema:.2f}, Lower={lower:.2f})")
# Signal 2: RSI Oversold
rsi = self.calculate_rsi(prices)
rsi_oversold = (rsi is not None and rsi < RSI_THRESHOLD)
return breakout
# HYBRID: Both must be true
hybrid_signal = bb_breakout and rsi_oversold
if hybrid_signal:
logger.info(f"[SIGNAL-HYBRID] {symbol} RSI={rsi:.1f} + BB-Breakout (EMA={ema:.2f}, Lower={lower:.2f})")
elif bb_breakout and not rsi_oversold:
logger.debug(f"[FILTERED] {symbol} BB-Breakout but RSI={rsi:.1f} (need <{RSI_THRESHOLD})")
elif rsi_oversold and not bb_breakout:
logger.debug(f"[FILTERED] {symbol} RSI={rsi:.1f} but no BB-Breakout")
return hybrid_signal
def get_fresh_balance(self):
try:
@ -132,7 +171,7 @@ class TradingBotV05:
self.portfolio_value = portfolio_value
self.max_trade_usdt = portfolio_value * MAX_POSITION_PCT
logger.info(f"[v0.5] USDT={usdt_available:.2f} | Portfolio={portfolio_value:.2f} | Max={self.max_trade_usdt:.2f}")
logger.info(f"[v0.5.1] USDT={usdt_available:.2f} | Portfolio={portfolio_value:.2f} | Max={self.max_trade_usdt:.2f}")
return usdt_available, portfolio_value
except:
return 0, 0
@ -192,7 +231,7 @@ class TradingBotV05:
'entry_time': datetime.now().isoformat()
}
logger.info(f"[BUY-v0.5] {symbol} {qty} @ {price} (BB Breakout)")
logger.info(f"[BUY-v0.5.1] {symbol} {qty} @ {price} (RSI+BB HYBRID)")
return order
except:
return None
@ -264,10 +303,10 @@ class TradingBotV05:
if len(self.price_history[symbol]) > 100:
self.price_history[symbol].pop(0)
# Find BEST Bollinger Bands signal
# Find HYBRID signal (RSI + BB both true)
best_signal = None
for symbol in SYMBOLS:
if symbol not in self.active_trades and self.is_bollinger_breakout(symbol):
if symbol not in self.active_trades and self.is_hybrid_buy_signal(symbol):
best_signal = symbol
break
@ -285,7 +324,7 @@ class TradingBotV05:
'portfolio_value': round(portfolio_val, 2),
'max_trade_usdt': round(self.max_trade_usdt, 2),
'timestamp': datetime.now().isoformat(),
'version': 'v0.5-bollinger-bands'
'version': 'v0.5.1-rsi-bb-hybrid'
}, f)
os.replace(temp, '/home/marc/bot-deploy/active_trades.json')
except:
@ -294,18 +333,18 @@ class TradingBotV05:
# Save P&L
self.save_pnl_to_db(portfolio_val, usdt_free)
logger.info(f"[CYCLE-END] Trades={len(self.active_trades)} | Portfolio={portfolio_val:.2f} [v0.5]")
logger.info(f"[CYCLE-END] Trades={len(self.active_trades)} | Portfolio={portfolio_val:.2f} [v0.5.1]")
logger.info("="*70)
if __name__ == '__main__':
import sys
bot = TradingBotV05()
bot = TradingBotV051()
if len(sys.argv) > 1 and sys.argv[1] == '--once':
bot.run_cycle()
else:
logger.info("[v0.5 START] Trading Bot with Bollinger Bands signals...")
logger.info("[v0.5.1 START] Trading Bot with RSI + Bollinger Bands HYBRID signals...")
while True:
try:
bot.run_cycle()

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Trading Bot Dashboard v0.5 (Bollinger Bands) - Auto-load 1-Day chart on page load"""
"""Trading Bot Dashboard v0.5.1 (RSI + Bollinger Bands HYBRID) - Auto-load 1-Day chart on page load"""
import sqlite3
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
@ -110,7 +110,7 @@ async def dashboard():
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Trading Bot v0.5</title>
<title>Trading Bot v0.5.1</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
*{margin:0;padding:0;box-sizing:border-box}
@ -170,7 +170,7 @@ body{font-family:Segoe UI,Arial;background:#1e1e1e;color:#d0d0d0;min-height:100v
<div class="container">
<div class="header">
<div><h1>🤖 Trading Bot v0.5</h1><p>P&L Analytics</p></div>
<div><h1>🤖 Trading Bot v0.5.1</h1><p>P&L Analytics</p></div>
<div class="status" id="st"> LOADING</div>
</div>