gym-anytrading

repository·master·Indexed 25 days ago

https://github.com/aminhp/gym-anytrading

A collection of OpenAI Gym environments for reinforcement learning-based trading algorithms in FOREX and Stock markets. It provides the TradingEnv abstract base class and concrete implementations ForexEnv and StocksEnv, supporting environment IDs 'forex-v0' and 'stocks-v0'. The library allows for custom data processing via the _process_data method and integrates with Stable-Baselines3 for training agents like A2C and PPO.

Tokens
4K
Snippets
15
Records
20
Agent score
82%

What's inside gym-anytrading

  1. Understand Trading Actions and Positions

    master

    To simplify the learning process for RL agents, gym-anytrading uses a reduced set of actions and positions compared to traditional trading systems.

    Trading Actions

    The action space is discrete and contains only two values:

    • 0: Sell
    • 1: Buy

    Trading Positions

    The environment manages two types of positions:

    • 0: Short (selling high to buy back lower)
    • 1: Long (buying low to sell higher)
  2. Install gym-anytrading

    master

    You can install the package via PIP or by cloning the repository for development.

    # Via PIP
    pip install gym-anytrading
    
    # From Repository
    git clone https://github.com/AminHP/gym-anytrading
    cd gym-anytrading
    pip install -e .
    
    # Or via direct zip installation
    pip install --upgrade --no-deps --force-reinstall https://github.com/AminHP/gym-anytrading/archive/master.zip
  3. Create a trading environment with gym.make()

    master

    You can create default trading environments for Forex or Stocks using gym.make().

    Available environment IDs:

    • forex-v0
    • stocks-v0
    import gymnasium as gym
    import gym_anytrading
    
    env = gym.make('forex-v0')
    # env = gym.make('stocks-v0')
  4. Extend TradingEnv with custom data processing

    master

    If you need to extract custom features or process data differently, you can extend ForexEnv or StocksEnv by overriding the _process_data method.

    Method 1: Overriding _process_data in a subclass (Recommended) This method allows you to define how the environment extracts prices and signal_features from the internal DataFrame based on the frame_bound and window_size.

    def my_process_data(env):
        start = env.frame_bound[0] - env.window_size
        end = env.frame_bound[1]
        prices = env.df.loc[:, 'Low'].to_numpy()[start:end]
        signal_features = env.df.loc[:, ['Close', 'Open', 'High', 'Low']].to_numpy()[start:end]
        return prices, signal_features
    
    class MyForexEnv(ForexEnv):
        _process_data = my_process_data
    
    env = MyForexEnv(df=FOREX_EURUSD_1H_ASK, window_size=12, frame_bound=(12, len(FOREX_EURUSD_1H_ASK)))
  5. Configure trading environments with custom parameters

    master

    When calling gym.make(), you can pass several parameters to customize the environment behavior:

    • df: A pandas DataFrame containing the market data.
    • window_size: The number of previous time steps to include in the observation.
    • frame_bound: A tuple (start, end) defining the range of the dataset to use. Note: The first element of frame_bound must be greater than or equal to window_size.
    • unit_side: Specifies the side for the unit (e.g., 'right').

    Example using provided datasets:

    from gym_anytrading.datasets import FOREX_EURUSD_1H_ASK, STOCKS_GOOGL
    import gymnasium as gym
    
    custom_env = gym.make(
        'forex-v0',
        df=FOREX_EURUSD_1H_ASK,
        window_size=10,
        frame_bound=(10, 300),
        unit_side='right'
    )
  6. Run a complete trading loop

    master

    A standard Gymnasium-compatible loop for interacting with the environment involves reset() and step(). The step() method returns observation, reward, terminated, truncated, and info.

    import gymnasium as gym
    import gym_anytrading
    
    env = gym.make('forex-v0', frame_bound=(50, 100), window_size=10)
    
    observation = env.reset(seed=2023)
    while True:
        action = env.action_space.sample()
        observation, reward, terminated, truncated, info = env.step(action)
        done = terminated or truncated
    
        if done:
            print("info:", info)
            break
  7. Render trading environment plots

    master

    The environment supports visual rendering of trades.

    • env.render(): Renders the current state (useful for step-by-step visualization).
    • env.unwrapped.render_all(): Renders the entire history of the environment. This is more efficient for viewing the full episode after training.

    In plots, Short positions are shown in red and Long positions are shown in green.

    env.reset()
    env.render()
    
    # Or for the full history:
    env.unwrapped.render_all()
  8. TradingEnv API Reference

    master

    TradingEnv is an abstract base class inheriting from gym.Env. It provides a general-purpose framework for trading markets.

    Public Properties

    • df: The pandas.DataFrame containing the dataset passed during construction.
    • prices: Real prices over time used for profit calculation and rendering.
    • signal_features: Extracted features used to create Gym observations.
    • window_size: The number of ticks (current and previous) returned in a single observation.
    • action_space: The Gym action space containing 0=Sell and 1=Buy.
    • observation_space: The Gym observation space. Observations are windows on signal_features from index current_tick - window_size + 1 to current_tick.
    • shape: The shape of a single observation.
    • history: Stores information for all steps taken.

    Public Methods

    • seed(): Standard Gym method to seed the environment.
    • reset(): Standard Gym method to reset the environment.
    • step(): Standard Gym method to advance the environment.
    • render(): Renders the information of the current tick.
    • render_all(): Renders the entire environment history.
    • close(): Standard Gym method to close the environment.

    Abstract Methods (to be implemented by subclasses)

    • _process_data(): Called in the constructor; must return (prices, signal_features).
    • _calculate_reward(): The reward function for the RL agent.
    • _update_profit(): Calculates and updates total profit (FinalMoney / StartingMoney).
    • max_possible_profit(): Returns the maximum theoretical profit regardless of fees.
  9. Inspect environment properties and max profit

    master

    You can access the underlying environment via env.unwrapped to inspect data shapes and calculate potential returns.

    Key attributes/methods:

    • unwrapped.shape: Shape of the observation space.
    • unwrapped.df.shape: Shape of the underlying DataFrame.
    • unwrapped.prices.shape: Shape of the price array.
    • unwrapped.signal_features.shape: Shape of the signal features array.
    • unwrapped.max_possible_profit(): Returns the maximum profit achievable if there were no trade fees, assuming a starting capital of 1.0.
    print("> shape:", env.unwrapped.shape)
    print("> max_possible_profit:", env.unwrapped.max_possible_profit())
  10. Train trading agents with Stable-Baselines3

    master

    To train reinforcement learning agents (like A2C or PPO) on gym-anytrading environments, initialize the model with a policy (e.g., MlpPolicy) and the environment, then call .learn().

    Note: If you want to use the built-in progress bar in model.learn(progress_bar=True), you must install the extra dependencies for Stable-Baselines3:

    pip install stable-baselines3[extra]
  11. Perform quantitative analysis using `quantstats`

    master

    After running an environment, you can extract the cumulative profit from env.unwrapped.history['total_profit'] to perform financial performance analysis. By converting this to a series of percentage changes (returns), you can use quantstats to generate full reports or HTML files.

    import quantstats as qs
    import pandas as pd
    
    qs.extend_pandas()
    
    # Extract total profit history and align with the original dataframe index
    net_worth = pd.Series(env.unwrapped.history['total_profit'], index=df.index[start_index+1:end_index])
    returns = net_worth.pct_change().iloc[1:]
    
    # Generate reports
    qs.reports.full(returns)
    qs.reports.html(returns, output='SB3_a2c_quantstats.html')