Team Ai
Modelpublic

ParallelLLC/algorithmic_trading

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
27likes32downloads
synthetic_data_generator.py240 linesDownload Raw Back to agentic_ai_system
1import pandas as pd2import numpy as np3from datetime import datetime, timedelta4import logging5from typing import Dict, List, Optional6 7logger = logging.getLogger(__name__)8 9class SyntheticDataGenerator:10    """11    Generates synthetic market data for testing and development purposes.12    Creates realistic price movements with volatility, trends, and market noise.13    """14    15    def __init__(self, config: Dict):16        self.config = config17        self.base_price = config.get('synthetic_data', {}).get('base_price', 100.0)18        self.volatility = config.get('synthetic_data', {}).get('volatility', 0.02)19        self.trend = config.get('synthetic_data', {}).get('trend', 0.001)20        self.noise_level = config.get('synthetic_data', {}).get('noise_level', 0.005)21        22        logger.info(f"Initialized SyntheticDataGenerator with base_price={self.base_price}, "23                   f"volatility={self.volatility}, trend={self.trend}")24    25    def generate_ohlcv_data(self, 26                           symbol: str = 'AAPL',27                           start_date: str = '2024-01-01',28                           end_date: str = '2024-12-31',29                           frequency: str = '1min') -> pd.DataFrame:30        """31        Generate synthetic OHLCV (Open, High, Low, Close, Volume) data.32        33        Args:34            symbol: Stock symbol35            start_date: Start date in YYYY-MM-DD format36            end_date: End date in YYYY-MM-DD format37            frequency: Data frequency ('1min', '5min', '1H', '1D')38            39        Returns:40            DataFrame with OHLCV data41        """42        logger.info(f"Generating synthetic OHLCV data for {symbol} from {start_date} to {end_date}")43        44        # Create datetime range45        start_dt = pd.to_datetime(start_date)46        end_dt = pd.to_datetime(end_date)47        48        # Generate timestamps based on frequency49        if frequency == '1min' or frequency == '1m':50            timestamps = pd.date_range(start=start_dt, end=end_dt, freq='1min')51        elif frequency == '5min' or frequency == '5m':52            timestamps = pd.date_range(start=start_dt, end=end_dt, freq='5min')53        elif frequency == '1H' or frequency == '1h':54            timestamps = pd.date_range(start=start_dt, end=end_dt, freq='1h')55        elif frequency == '1D' or frequency == '1d':56            timestamps = pd.date_range(start=start_dt, end=end_dt, freq='1D')57        else:58            raise ValueError(f"Unsupported frequency: {frequency}")59        60        # Generate price data61        prices = self._generate_price_series(len(timestamps))62        63        # Generate OHLCV data64        data = []65        current_price = self.base_price66        67        for i, timestamp in enumerate(timestamps):68            # Add trend and noise69            trend_component = self.trend * i70            noise = np.random.normal(0, self.noise_level)71            72            # Generate OHLC from current price73            open_price = current_price * (1 + noise)74            close_price = open_price * (1 + np.random.normal(0, self.volatility))75            76            # Generate high and low77            price_range = abs(close_price - open_price) * np.random.uniform(1.5, 3.0)78            high_price = max(open_price, close_price) + price_range * np.random.uniform(0, 0.5)79            low_price = min(open_price, close_price) - price_range * np.random.uniform(0, 0.5)80            81            # Generate volume (correlated with price movement)82            volume = np.random.randint(1000, 100000) * (1 + abs(close_price - open_price) / open_price)83            84            data.append({85                'timestamp': timestamp,86                'symbol': symbol,87                'open': round(open_price, 2),88                'high': round(high_price, 2),89                'low': round(low_price, 2),90                'close': round(close_price, 2),91                'volume': int(volume)92            })93            94            current_price = close_price95        96        df = pd.DataFrame(data)97        logger.info(f"Generated {len(df)} data points for {symbol}")98        return df99    100    def generate_tick_data(self, 101                          symbol: str = 'AAPL',102                          duration_minutes: int = 60,103                          tick_interval_ms: int = 1000) -> pd.DataFrame:104        """105        Generate high-frequency tick data for testing.106        107        Args:108            symbol: Stock symbol109            duration_minutes: Duration in minutes110            tick_interval_ms: Interval between ticks in milliseconds111            112        Returns:113            DataFrame with tick data114        """115        logger.info(f"Generating tick data for {symbol} for {duration_minutes} minutes")116        117        num_ticks = (duration_minutes * 60 * 1000) // tick_interval_ms118        timestamps = pd.date_range(119            start=datetime.now(),120            periods=num_ticks,121            freq=f'{tick_interval_ms}ms'122        )123        124        # Generate price series with more noise for tick data125        base_prices = self._generate_price_series(num_ticks, volatility=self.volatility * 2)126        127        data = []128        for i, (timestamp, base_price) in enumerate(zip(timestamps, base_prices)):129            # Add micro-movements130            tick_price = base_price * (1 + np.random.normal(0, self.noise_level * 0.5))131            132            data.append({133                'timestamp': timestamp,134                'symbol': symbol,135                'price': round(tick_price, 4),136                'volume': np.random.randint(1, 100)137            })138        139        df = pd.DataFrame(data)140        logger.info(f"Generated {len(df)} tick data points for {symbol}")141        return df142    143    def _generate_price_series(self, length: int, volatility: Optional[float] = None) -> np.ndarray:144        """145        Generate a realistic price series using geometric Brownian motion.146        147        Args:148            length: Number of price points149            volatility: Price volatility (if None, uses self.volatility)150            151        Returns:152            Array of prices153        """154        if volatility is None:155            volatility = self.volatility156        157        # Geometric Brownian motion parameters158        mu = self.trend  # drift159        sigma = volatility  # volatility160        161        # Generate random walks162        dt = 1.0 / length163        t = np.linspace(0, 1, length)164        165        # Brownian motion166        dW = np.random.normal(0, np.sqrt(dt), length)167        W = np.cumsum(dW)168        169        # Geometric Brownian motion170        S = self.base_price * np.exp((mu - 0.5 * sigma**2) * t + sigma * W)171        172        return S173    174    def save_to_csv(self, df: pd.DataFrame, filepath: str) -> None:175        """176        Save generated data to CSV file.177        178        Args:179            df: DataFrame to save180            filepath: Path to save the CSV file181        """182        df.to_csv(filepath, index=False)183        logger.info(f"Saved synthetic data to {filepath}")184    185    def generate_market_scenarios(self, scenario_type: str = 'normal') -> pd.DataFrame:186        """187        Generate data for different market scenarios.188        189        Args:190            scenario_type: Type of scenario ('normal', 'volatile', 'trending', 'crash')191            192        Returns:193            DataFrame with scenario-specific data194        """195        logger.info(f"Generating {scenario_type} market scenario")196        197        if scenario_type == 'normal':198            return self.generate_ohlcv_data()199        elif scenario_type == 'volatile':200            # High volatility scenario201            self.volatility *= 3202            data = self.generate_ohlcv_data()203            self.volatility /= 3  # Reset204            return data205        elif scenario_type == 'trending':206            # Strong upward trend207            self.trend *= 5208            data = self.generate_ohlcv_data()209            self.trend /= 5  # Reset210            return data211        elif scenario_type == 'crash':212            # Market crash scenario213            original_volatility = self.volatility214            original_trend = self.trend215            216            self.volatility *= 5217            self.trend = -0.01  # Strong downward trend218            219            try:220                data = self.generate_ohlcv_data()221            finally:222                # Reset parameters223                self.volatility = original_volatility224                self.trend = original_trend225            226            return data227        else:228            raise ValueError(f"Unknown scenario type: {scenario_type}") 229 230    def generate_data(self) -> pd.DataFrame:231        """232        Generate synthetic OHLCV data using config defaults.233        Returns:234            DataFrame with OHLCV data235        """236        symbol = self.config.get('trading', {}).get('symbol', 'AAPL')237        start_date = self.config.get('synthetic_data', {}).get('start_date', '2024-01-01')238        end_date = self.config.get('synthetic_data', {}).get('end_date', '2024-12-31')239        frequency = self.config.get('synthetic_data', {}).get('frequency', '1min')240        return self.generate_ohlcv_data(symbol=symbol, start_date=start_date, end_date=end_date, frequency=frequency)