Initial commit: Gold Trading Simulator with AI-powered analysis

This commit is contained in:
Krikorios
2025-11-16 00:50:04 +02:00
commit 72c1d3adb7
128 changed files with 16232 additions and 0 deletions
+198
View File
@@ -0,0 +1,198 @@
import random
import time
from datetime import datetime, timedelta
from typing import List, Optional
from app.schemas.schemas import PriceData
class GoldPriceSimulator:
"""
Simulates realistic gold price movements without external API calls.
Uses Geometric Brownian Motion for realistic price action.
"""
def __init__(self, initial_price: float = 2650.0):
"""
Initialize the simulator with a starting price.
Args:
initial_price: Starting gold price in USD per oz (default ~current market price)
"""
self.base_price = initial_price
self.current_price = initial_price
self.volatility = 0.0008 # Daily volatility (0.08%)
self.drift = 0.00001 # Slight upward drift
self.last_update = time.time()
# For trend simulation
self.trend_direction = 1 # 1 for up, -1 for down
self.trend_strength = 0.0001
self.trend_duration = 0
self.max_trend_duration = 100 # Max ticks before trend change
def _calculate_price_change(self) -> float:
"""Calculate the next price change using Geometric Brownian Motion."""
# Random walk component
random_shock = random.gauss(0, 1) * self.volatility
# Trend component (changes periodically)
self.trend_duration += 1
if self.trend_duration > self.max_trend_duration:
# Change trend direction
self.trend_direction = random.choice([1, -1])
self.trend_strength = random.uniform(0.00005, 0.0002)
self.trend_duration = 0
self.max_trend_duration = random.randint(50, 200)
trend_component = self.trend_direction * self.trend_strength
# Mean reversion (pulls price back toward base)
mean_reversion = (self.base_price - self.current_price) * 0.00001
# Combine components
total_change = self.drift + random_shock + trend_component + mean_reversion
return self.current_price * total_change
def get_current_price(self) -> float:
"""Get the current simulated gold price."""
# Update price based on time elapsed
current_time = time.time()
time_elapsed = current_time - self.last_update
# Update price (simulating continuous price movement)
if time_elapsed > 0:
# Multiple small updates for smoother price action
updates = max(1, int(time_elapsed))
for _ in range(min(updates, 10)): # Cap at 10 updates to avoid huge jumps
price_change = self._calculate_price_change()
self.current_price += price_change
# Keep price within reasonable bounds (±20% from base)
self.current_price = max(
self.base_price * 0.8,
min(self.base_price * 1.2, self.current_price)
)
self.last_update = current_time
return round(self.current_price, 2)
def get_live_candle(self, interval: str = "1min") -> PriceData:
"""
Generate a live price candle for the current interval.
Args:
interval: Time interval (1min, 5min, 15min, 30min, 60min)
Returns:
PriceData object with OHLC values
"""
current_price = self.get_current_price()
# Map intervals to seconds
interval_map = {
"1min": 60,
"5min": 5 * 60,
"15min": 15 * 60,
"30min": 30 * 60,
"60min": 60 * 60,
}
interval_seconds = interval_map.get(interval, 60)
current_time = int(time.time())
# Round up to next interval boundary to ensure newest timestamp
timestamp = ((current_time // interval_seconds) + 1) * interval_seconds
# Generate OHLC with small realistic variance
variance = current_price * 0.0005 # 0.05% variance
open_price = current_price + random.uniform(-variance, variance)
close_price = current_price + random.uniform(-variance, variance)
high_price = max(open_price, close_price) + random.uniform(0, variance)
low_price = min(open_price, close_price) - random.uniform(0, variance)
return PriceData(
time=timestamp,
open=round(open_price, 2),
high=round(high_price, 2),
low=round(low_price, 2),
close=round(close_price, 2),
)
def generate_historical_data(
self,
interval: str = "daily",
points: int = 100
) -> List[PriceData]:
"""
Generate historical price data using the simulator.
Args:
interval: Time interval (daily, 1min, 5min, etc.)
points: Number of data points to generate
Returns:
List of PriceData objects in chronological order
"""
# Map intervals to seconds
interval_map = {
"daily": 24 * 60 * 60,
"1min": 60,
"5min": 5 * 60,
"15min": 15 * 60,
"30min": 30 * 60,
"60min": 60 * 60,
}
interval_seconds = interval_map.get(interval, 24 * 60 * 60)
# Start from past and work forward
end_time = int(time.time())
start_time = end_time - (interval_seconds * points)
price_data = []
current_sim_price = self.base_price
for i in range(points):
timestamp = start_time + (interval_seconds * i)
# Simulate price evolution
price_change = random.gauss(0, 1) * self.volatility * current_sim_price
trend = random.uniform(-0.0001, 0.0001) * current_sim_price
current_sim_price += price_change + trend
# Keep within bounds
current_sim_price = max(
self.base_price * 0.85,
min(self.base_price * 1.15, current_sim_price)
)
# Generate OHLC for this candle
candle_variance = current_sim_price * 0.002 # 0.2% intra-candle variance
open_price = current_sim_price + random.uniform(-candle_variance/2, candle_variance/2)
close_price = current_sim_price + random.uniform(-candle_variance/2, candle_variance/2)
high_price = max(open_price, close_price) + random.uniform(0, candle_variance)
low_price = min(open_price, close_price) - random.uniform(0, candle_variance)
price_data.append(
PriceData(
time=timestamp,
open=round(open_price, 2),
high=round(high_price, 2),
low=round(low_price, 2),
close=round(close_price, 2),
)
)
# Set current price to the last closing price for continuity
if price_data:
self.current_price = price_data[-1].close
self.last_update = time.time()
return price_data
# Global simulator instance (maintains state across requests)
gold_simulator = GoldPriceSimulator(initial_price=2650.0)