fixed showing all moves
This commit is contained in:
parent
44b02b4e7d
commit
b0a57c5330
83
realtime.py
83
realtime.py
@ -30,6 +30,9 @@ class BinanceHistoricalData:
|
||||
"""
|
||||
def __init__(self):
|
||||
self.base_url = "https://api.binance.com/api/v3"
|
||||
self.cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cache')
|
||||
if not os.path.exists(self.cache_dir):
|
||||
os.makedirs(self.cache_dir)
|
||||
|
||||
def get_historical_candles(self, symbol, interval_seconds=3600, limit=1000):
|
||||
"""
|
||||
@ -60,6 +63,14 @@ class BinanceHistoricalData:
|
||||
# Format symbol for Binance API (remove slash)
|
||||
formatted_symbol = symbol.replace("/", "")
|
||||
|
||||
# Check if we have cached data first
|
||||
cache_file = self._get_cache_filename(formatted_symbol, interval)
|
||||
cached_data = self._load_from_cache(formatted_symbol, interval)
|
||||
|
||||
if cached_data is not None and len(cached_data) >= limit:
|
||||
logger.info(f"Using cached historical data for {symbol} ({interval})")
|
||||
return cached_data
|
||||
|
||||
try:
|
||||
# Build URL for klines endpoint
|
||||
url = f"{self.base_url}/klines"
|
||||
@ -93,14 +104,48 @@ class BinanceHistoricalData:
|
||||
# Sort by timestamp
|
||||
df = df.sort_values("timestamp")
|
||||
|
||||
# Save to cache for future use
|
||||
self._save_to_cache(df, formatted_symbol, interval)
|
||||
|
||||
logger.info(f"Fetched {len(df)} candles for {symbol} ({interval})")
|
||||
return df
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching historical data from Binance: {str(e)}")
|
||||
# Return cached data if we have it, even if it's not enough
|
||||
if cached_data is not None:
|
||||
logger.warning(f"Using cached data instead (may be incomplete)")
|
||||
return cached_data
|
||||
# Return empty dataframe on error
|
||||
return pd.DataFrame()
|
||||
|
||||
def _get_cache_filename(self, symbol, interval):
|
||||
"""Get filename for cache file"""
|
||||
return os.path.join(self.cache_dir, f"{symbol}_{interval}_candles.csv")
|
||||
|
||||
def _load_from_cache(self, symbol, interval):
|
||||
"""Load candles from cache file"""
|
||||
try:
|
||||
cache_file = self._get_cache_filename(symbol, interval)
|
||||
if os.path.exists(cache_file):
|
||||
df = pd.read_csv(cache_file)
|
||||
df["timestamp"] = pd.to_datetime(df["timestamp"])
|
||||
return df
|
||||
except Exception as e:
|
||||
logger.error(f"Error loading cached data: {str(e)}")
|
||||
return None
|
||||
|
||||
def _save_to_cache(self, df, symbol, interval):
|
||||
"""Save candles to cache file"""
|
||||
try:
|
||||
cache_file = self._get_cache_filename(symbol, interval)
|
||||
df.to_csv(cache_file, index=False)
|
||||
logger.info(f"Saved {len(df)} candles to cache: {cache_file}")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error saving to cache: {str(e)}")
|
||||
return False
|
||||
|
||||
def get_recent_trades(self, symbol, limit=1000):
|
||||
"""Get recent trades for a symbol"""
|
||||
formatted_symbol = symbol.replace("/", "")
|
||||
@ -553,6 +598,7 @@ class TickStorage:
|
||||
try:
|
||||
# Load data for different timeframes
|
||||
timeframes = [
|
||||
(1, '1s'), # 1 second
|
||||
(60, '1m'), # 1 minute
|
||||
(300, '5m'), # 5 minutes
|
||||
(900, '15m'), # 15 minutes
|
||||
@ -562,7 +608,22 @@ class TickStorage:
|
||||
]
|
||||
|
||||
for interval_seconds, interval_key in timeframes:
|
||||
df = historical_data.get_historical_candles(symbol, interval_seconds)
|
||||
# Set appropriate limits based on timeframe
|
||||
limit = 1000 # Default
|
||||
if interval_seconds == 1:
|
||||
limit = 500 # 1s is too much data, limit to 500
|
||||
elif interval_seconds < 60:
|
||||
limit = 750 # For seconds-level data
|
||||
elif interval_seconds < 300:
|
||||
limit = 1000 # 1m
|
||||
elif interval_seconds < 900:
|
||||
limit = 500 # 5m
|
||||
elif interval_seconds < 3600:
|
||||
limit = 300 # 15m
|
||||
else:
|
||||
limit = 200 # hourly/daily data
|
||||
|
||||
df = historical_data.get_historical_candles(symbol, interval_seconds, limit)
|
||||
if df is not None and not df.empty:
|
||||
logger.info(f"Loaded {len(df)} historical candles for {symbol} ({interval_key})")
|
||||
|
||||
@ -578,7 +639,9 @@ class TickStorage:
|
||||
}
|
||||
self.candles[interval_key].append(candle)
|
||||
|
||||
# Also use the close price to simulate ticks
|
||||
# For 1m and above, also use the close price to simulate ticks
|
||||
# but don't do this for seconds-level data as it creates too many ticks
|
||||
if interval_seconds >= 60 and interval_key == '1m':
|
||||
self.add_tick(
|
||||
price=row['close'],
|
||||
volume=row['volume'],
|
||||
@ -904,8 +967,13 @@ class RealTimeChart:
|
||||
sell_times = []
|
||||
sell_prices = []
|
||||
|
||||
# Use only last 20 positions for clarity
|
||||
for position in self.positions[-20:]:
|
||||
# Use all positions for chart display
|
||||
# Filter recent ones based on visible time range
|
||||
now = datetime.now()
|
||||
time_limit = now - timedelta(hours=24) # Show at most 24h of trades
|
||||
|
||||
for position in self.positions:
|
||||
if position.entry_timestamp > time_limit:
|
||||
if position.action == "BUY":
|
||||
buy_times.append(position.entry_timestamp)
|
||||
buy_prices.append(position.entry_price)
|
||||
@ -1112,14 +1180,17 @@ class RealTimeChart:
|
||||
winning_trades = sum(1 for p in self.positions if p.pnl and p.pnl > 0)
|
||||
win_rate = winning_trades / total_trades * 100 if total_trades > 0 else 0
|
||||
|
||||
# Format display colors for PnL
|
||||
pnl_color = "green" if self.accumulative_pnl >= 0 else "red"
|
||||
|
||||
summary_row = html.Tr([
|
||||
html.Td("SUMMARY", colSpan=2, style={"fontWeight": "bold"}),
|
||||
html.Td(f"Trades: {total_trades}"),
|
||||
html.Td(f"Win Rate: {win_rate:.1f}%"),
|
||||
html.Td("Total PnL:", style={"fontWeight": "bold"}),
|
||||
html.Td(f"${self.accumulative_pnl:.2f}",
|
||||
style={"color": "green" if self.accumulative_pnl >= 0 else "red", "fontWeight": "bold"}),
|
||||
html.Td("")
|
||||
style={"color": pnl_color, "fontWeight": "bold"}),
|
||||
html.Td(f"Balance: ${self.current_balance:.2f}")
|
||||
], style={"backgroundColor": "rgba(80, 80, 80, 0.3)"})
|
||||
|
||||
# Create the table with improved styling
|
||||
|
@ -516,17 +516,27 @@ class RLTrainingIntegrator:
|
||||
if len(self.price_history) > self.price_history_max_len:
|
||||
self.price_history = self.price_history[-self.price_history_max_len:]
|
||||
|
||||
# Normalize rewards to be realistic for crypto trading (smaller values)
|
||||
normalized_reward = reward * 0.1 # Scale down rewards
|
||||
if abs(normalized_reward) > 5.0: # Cap maximum reward value
|
||||
normalized_reward = 5.0 if normalized_reward > 0 else -5.0
|
||||
|
||||
# Update session PnL and balance
|
||||
self.session_step += 1
|
||||
self.session_pnl += reward
|
||||
self.session_pnl += normalized_reward
|
||||
|
||||
# Increase balance based on reward
|
||||
self.session_balance += reward
|
||||
# Increase balance based on reward - cap to reasonable values
|
||||
self.session_balance += normalized_reward
|
||||
self.session_balance = min(self.session_balance, 1000.0) # Cap maximum balance
|
||||
self.session_balance = max(self.session_balance, 0.0) # Prevent negative balance
|
||||
|
||||
# Update chart's accumulativePnL and balance if available
|
||||
if self.chart:
|
||||
if hasattr(self.chart, 'accumulative_pnl'):
|
||||
self.chart.accumulative_pnl = self.session_pnl
|
||||
# Cap accumulated PnL to reasonable values
|
||||
self.chart.accumulative_pnl = min(self.chart.accumulative_pnl, 500.0)
|
||||
self.chart.accumulative_pnl = max(self.chart.accumulative_pnl, -100.0)
|
||||
|
||||
if hasattr(self.chart, 'current_balance'):
|
||||
self.chart.current_balance = self.session_balance
|
||||
@ -751,7 +761,7 @@ def _add_trade_compat(chart, price, timestamp, amount, pnl=0.0, action="BUY"):
|
||||
position.close(price, timestamp)
|
||||
# Use realistic PnL values rather than the enormous ones from the model
|
||||
# Cap PnL to reasonable values based on position size and price
|
||||
max_reasonable_pnl = price * amount * 0.10 # Max 10% profit
|
||||
max_reasonable_pnl = price * amount * 0.05 # Max 5% profit per trade
|
||||
if abs(pnl) > max_reasonable_pnl:
|
||||
if pnl > 0:
|
||||
pnl = max_reasonable_pnl * 0.8 # Positive but reasonable
|
||||
@ -762,11 +772,14 @@ def _add_trade_compat(chart, price, timestamp, amount, pnl=0.0, action="BUY"):
|
||||
# Update chart's accumulated PnL if available
|
||||
if hasattr(chart, 'accumulative_pnl'):
|
||||
chart.accumulative_pnl += pnl
|
||||
# Cap accumulated PnL to reasonable values
|
||||
chart.accumulative_pnl = min(chart.accumulative_pnl, 500.0)
|
||||
chart.accumulative_pnl = max(chart.accumulative_pnl, -100.0)
|
||||
|
||||
# Add to positions list, keeping only the last 10 if we have more
|
||||
# Add to positions list, keeping only the last 200 for chart display
|
||||
chart.positions.append(position)
|
||||
if len(chart.positions) > 10:
|
||||
chart.positions = chart.positions[-10:]
|
||||
if len(chart.positions) > 200:
|
||||
chart.positions = chart.positions[-200:]
|
||||
|
||||
logger.info(f"Added {action} trade: price={price:.2f}, amount={amount}, pnl={pnl:.2f}")
|
||||
return True
|
||||
|
Loading…
x
Reference in New Issue
Block a user