This commit is contained in:
Dobromir Popov 2025-02-01 23:26:42 +02:00
parent 773b1b6b76
commit 015b79c395
2 changed files with 115 additions and 76 deletions

View File

@ -1,10 +1,12 @@
#!/usr/bin/env python3
import asyncio
import os
import ccxt.async_support as ccxt
import torch
import torch.nn as nn
import torch.optim as optim
import asyncio
from collections import deque
import numpy as np
from collections import deque
# ------------------------------
# Neural Network Architecture
@ -12,8 +14,8 @@ import numpy as np
class TradingModel(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim):
super(TradingModel, self).__init__()
# This is a simplified network template.
# A production-grade 8B model would involve model parallelism and a deep transformer or other architecture.
# This is a simplified feed-forward model.
# A production-grade 8B parameter model would need a distributed strategy.
self.net = nn.Sequential(
nn.Linear(input_dim, hidden_dim),
nn.ReLU(),
@ -47,11 +49,12 @@ class ReplayBuffer:
# ------------------------------
def compute_indicators(candle, additional_data):
"""
Combine candle data (H, L, O, C, V) with additional indicators.
In production, use proper TA libraries (e.g., TA-Lib) to compute RSI, stochastic oscillator, etc.
Combine basic OHLCV candle data with additional sentiment/indicator data.
In production, you might use dedicated libraries (like TALib) to calculate RSI, stochastic,
and support up to 100 channels.
"""
features = []
# Base candlestick features:
# Base candle features: open, high, low, close, volume
features.extend([
candle.get('open', 0.0),
candle.get('high', 0.0),
@ -60,43 +63,57 @@ def compute_indicators(candle, additional_data):
candle.get('volume', 0.0)
])
# Append additional indicator values (e.g., sentiment score, news volume, etc.)
# Append additional indicators (e.g., sentiment, news volume, etc.)
for key, value in additional_data.items():
features.append(value)
return np.array(features, dtype=np.float32)
# ------------------------------
# Simulated Live Data Streams
# Data Ingestion from MEXC: Live Candle Data
# ------------------------------
async def get_live_candle_data():
async def get_live_candle_data(exchange, symbol, timeframe='1m'):
"""
This function should connect to your live data feed.
For demonstration purposes, we simulate new candlestick data.
Fetch the latest OHLCV candle for the given symbol and timeframe.
MEXC (or other exchanges via ccxt) returns a list of candles:
[ timestamp, open, high, low, close, volume ]
We use limit=1 to get the last candle.
"""
await asyncio.sleep(1) # simulate network/data latency
return {
'open': np.random.rand(),
'high': np.random.rand(),
'low': np.random.rand(),
'close': np.random.rand(),
'volume': np.random.rand()
}
try:
ohlcv = await exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=1)
if ohlcv and len(ohlcv) > 0:
ts, open_, high, low, close, volume = ohlcv[-1]
candle = {
'timestamp': ts,
'open': open_,
'high': high,
'low': low,
'close': close,
'volume': volume
}
return candle
return None
except Exception as e:
print("Error fetching candle data:", e)
return None
# ------------------------------
# Simulated Sentiment Data
# ------------------------------
async def get_sentiment_data():
"""
Simulate fetching live sentiment data from external sources.
Replace this with integration to actual X feeds or news APIs.
Simulate fetching live sentiment data.
In production, integrate sentiment analysis from social media, news APIs, etc.
"""
await asyncio.sleep(1)
await asyncio.sleep(0.1) # Simulated latency
return {
'sentiment_score': np.random.rand(), # e.g., normalized sentiment between 0 and 1
'sentiment_score': np.random.rand(), # Example: normalized between 0 and 1
'news_volume': np.random.rand(),
'social_engagement': np.random.rand()
}
# ------------------------------
# RL Agent with Continuous Training
# RL Agent with Continuous Learning
# ------------------------------
class ContinuousRLAgent:
def __init__(self, model, optimizer, replay_buffer, batch_size=32):
@ -104,14 +121,13 @@ class ContinuousRLAgent:
self.optimizer = optimizer
self.replay_buffer = replay_buffer
self.batch_size = batch_size
# Placeholder loss function; a real-world RL agent often has a more complex loss (e.g., Q-learning loss)
# For demonstration, we use a basic MSE loss.
self.loss_fn = nn.MSELoss()
def act(self, state):
"""
Compute the action given the latest state.
In production, the network output should map to a confidence or Q-values for actions.
Action mapping (for example): 0: SELL, 1: HOLD, 2: BUY.
Given the latest state, decide on an action.
Mapping: 0: SELL, 1: HOLD, 2: BUY.
"""
state_tensor = torch.tensor(state, dtype=torch.float32).unsqueeze(0)
with torch.no_grad():
@ -121,15 +137,14 @@ class ContinuousRLAgent:
def train_step(self):
"""
Perform one training step using a batch sampled from the replay buffer.
In RL, targets are computed from rewards and estimated future returns.
Perform one training step using a sample from the replay buffer.
Note: A true RL implementation would incorporate rewards and discounted returns.
"""
if len(self.replay_buffer) < self.batch_size:
return
return # Not enough samples yet
batch = self.replay_buffer.sample(self.batch_size)
states, rewards, next_states, dones = [], [], [], []
for experience in batch:
state, reward, next_state, done = experience
states.append(state)
@ -141,7 +156,7 @@ class ContinuousRLAgent:
targets_tensor = torch.tensor(rewards, dtype=torch.float32).unsqueeze(1)
outputs = self.model(states_tensor)
# For simplicity, assume we use a single output value to represent the signal.
# For demonstration, we use the first output as our estimation.
predictions = outputs[:, 0].unsqueeze(1)
loss = self.loss_fn(predictions, targets_tensor)
@ -150,82 +165,104 @@ class ContinuousRLAgent:
self.optimizer.step()
# ------------------------------
# Trading Bot: Integration with Jupiter API (Solana)
# Trading Bot: Execution with MEXC API
# ------------------------------
class TradingBot:
def __init__(self, rl_agent):
def __init__(self, rl_agent, exchange, symbol='BTC/USDT', trade_amount=0.001):
self.rl_agent = rl_agent
# Initialize Jupiter API client for Solana trading
# Hypothetical client initialization (substitute with an actual library/client):
# self.jupiter_client = JupiterClient(api_key='YOUR_API_KEY')
self.exchange = exchange
self.symbol = symbol
self.trade_amount = trade_amount # Amount to trade (in base currency)
async def execute_trade(self, action):
"""
Translate the agent's selected action into a trade order.
Action mapping example: 0 => SELL, 1 => HOLD, 2 => BUY.
Convert the RL agent's decision into a market order.
Action mapping: 0 => SELL, 1 => HOLD, 2 => BUY.
"""
if action == 0:
print("Executing SELL order")
# self.jupiter_client.sell(...actual trade parameters...)
await self.place_market_order('sell')
elif action == 2:
print("Executing BUY order")
# self.jupiter_client.buy(...actual trade parameters...)
await self.place_market_order('buy')
else:
print("Holding position")
print("Holding position - no order executed")
async def trading_loop(self):
async def place_market_order(self, side):
"""
Main trading loop:
Ingest live data.
Compute features.
Let the agent decide on an action.
Execute trades.
Store experience and train continuously.
Place a market order on MEXC using ccxt.
"""
try:
order = await self.exchange.create_order(self.symbol, 'market', side, self.trade_amount, None)
print(f"Order executed: {order}")
except Exception as e:
print(f"Error executing {side} order:", e)
async def trading_loop(self, timeframe='1m'):
"""
Main loop:
- Fetch live candlestick and sentiment data.
- Compute state features.
- Let the RL agent decide an action.
- Execute market orders.
- Store experience and perform continuous training.
"""
while True:
# Fetch latest data (you might aggregate data for different time frames)
candle = await get_live_candle_data()
sentiment = await get_sentiment_data()
# In practice, merge technical indicators computed on candle data with sentiment data.
indicators = sentiment # For demo, sentiment is our extra feature set.
candle = await get_live_candle_data(self.exchange, self.symbol, timeframe)
if candle is None:
await asyncio.sleep(1)
continue
# Compute state features
state = compute_indicators(candle, indicators)
# Get an action from the RL agent (0: Sell, 1: Hold, 2: Buy)
sentiment = await get_sentiment_data()
state = compute_indicators(candle, sentiment)
action = self.rl_agent.act(state)
await self.execute_trade(action)
# Simulate reward computation (in reality, your reward function should be based on trading performance)
# Simulate reward computation. In production, use trading performance to compute reward.
reward = np.random.rand()
next_state = state # For demonstration, we reuse the state; in practice, next_state is computed after action execution.
done = False # Flag to indicate episode termination if needed
# Store the experience in the replay buffer
next_state = state # In a real system, this would be updated after the trade.
done = False
self.rl_agent.replay_buffer.add((state, reward, next_state, done))
# Run a training step to update the network continuously
self.rl_agent.train_step()
# Sleep to conform to the data frequency (adjust the delay as needed)
await asyncio.sleep(0.5)
# Wait to match the candle timeframe (for a 1m candle, sleep 60 seconds)
await asyncio.sleep(60)
# ------------------------------
# Main Orchestration Loop
# Main Execution Loop
# ------------------------------
async def main_loop():
# Define dimensions. For instance: 5 for basic candlestick data + additional channels (e.g., 3 here; expand as necessary)
input_dim = 5 + 3 # Adjust this to support up to 100 additional indicator channels
hidden_dim = 128 # Placeholder; for an 8B parameter model, this will be much larger and distributed.
output_dim = 3 # Action space: Sell, Hold, Buy
# Retrieve MEXC API credentials from environment variables or replace with your keys.
mexc_api_key = os.environ.get('MEXC_API_KEY', 'YOUR_API_KEY')
mexc_api_secret = os.environ.get('MEXC_API_SECRET', 'YOUR_SECRET_KEY')
# Create the MEXC exchange instance (ccxt asynchronous)
exchange = ccxt.mexc({
'apiKey': mexc_api_key,
'secret': mexc_api_secret,
'enableRateLimit': True,
})
# Define the model input dimensions.
# Base candle features (5: open, high, low, close, volume) + simulated 3 sentiment features
input_dim = 8
hidden_dim = 128
output_dim = 3 # SELL, HOLD, BUY
model = TradingModel(input_dim, hidden_dim, output_dim)
optimizer = optim.Adam(model.parameters(), lr=1e-4)
replay_buffer = ReplayBuffer(capacity=10000)
rl_agent = ContinuousRLAgent(model, optimizer, replay_buffer, batch_size=32)
trading_bot = TradingBot(rl_agent)
# Start the continuous trading loop
await trading_bot.trading_loop()
trading_bot = TradingBot(rl_agent, exchange, symbol='BTC/USDT', trade_amount=0.001)
try:
# Begin the continuous trading loop (using 1-minute candles)
await trading_bot.trading_loop(timeframe='1m')
except Exception as e:
print("Error in trading loop:", e)
finally:
await exchange.close()
if __name__ == "__main__":
asyncio.run(main_loop())

2
crypto/brian/readme.md Normal file
View File

@ -0,0 +1,2 @@
pip install ccxt torch numpy