File size: 2,226 Bytes
75c7554
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import numpy as np
import pandas as pd
import os

def generate_synthetic_data(num_days=30, output_path="synthetic_bess_data.csv"):
    """
    Generate synthetic time-series data for BESS RL Environment.
    Features:
    - price: Electricity price ($/MWh), higher during peak hours (e.g. 17:00-21:00)
    - load: Building/Grid load (MW), peak daytime.
    - frequency: Grid frequency (Hz), centered around 50 or 60. We use a standardized deviation -1.0 to 1.0.
    """
    total_hours = num_days * 24
    
    # Time
    hours_of_day = np.arange(total_hours) % 24
    
    # Price ($/MWh)
    # Base price around $40. Peak price (17-21) goes up to $150.
    base_price = np.random.normal(40, 5, total_hours)
    peak_multiplier = np.where((hours_of_day >= 17) & (hours_of_day <= 21), 3.0, 1.0)
    price = base_price * peak_multiplier + np.random.normal(0, 10, total_hours)
    price = np.clip(price, 10, None) # Min price $10
    
    # Load (MW)
    # Base load around 10MW, peaks during day 9-18
    base_load = np.random.normal(10, 2, total_hours)
    load_multiplier = np.where((hours_of_day >= 9) & (hours_of_day <= 18), 1.5, 1.0)
    load = base_load * load_multiplier + np.random.normal(0, 1.5, total_hours)
    load = np.clip(load, 2, None)
    
    # Frequency Deviation (Hz)
    # Ideally 0. Deviates occasionally.
    # Simple autoregressive model for frequency to simulate persistence
    freq_dev = np.zeros(total_hours)
    freq_dev[0] = np.random.normal(0, 0.05)
    for i in range(1, total_hours):
        freq_dev[i] = 0.7 * freq_dev[i-1] + np.random.normal(0, 0.02)
    
    freq_dev = np.clip(freq_dev, -0.5, 0.5)
    
    df = pd.DataFrame({
        "hour_of_day": hours_of_day,
        "price": price,
        "load": load,
        "frequency_deviation": freq_dev
    })
    
    # Ensure directory exists if saving
    if output_path is not None:
        os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
        df.to_csv(output_path, index=False)
        print(f"Saved synthetic data to {output_path}")
        
    return df

if __name__ == "__main__":
    generate_synthetic_data(num_days=365, output_path=os.path.join(os.path.dirname(__file__), "synthetic_bess_data.csv"))