Adding a Strategy

To add a custom trading strategy to the project, follow these guidelines. Every custom strategy must extend the BaseStrategy class and adhere to the specified directory and file structure.

Directory Structure

  1. Create a directory for your custom strategy inside custom_modules/strategies/:

    custom_modules/strategies/<your strategy name>/
  2. Implement your strategy class in a file named strategy.py within the directory.

  3. Assuming the strategy is named my_strategy:

    custom_modules/
    ├── strategies/
    │   ├── my_strategy/
    │   │   └── strategy.py

    By following these guidelines, your custom strategy will integrate seamlessly with the project, ensuring compatibility and adherence to project conventions. This modular structure allows for easy addition, management, and testing of new strategies.

Implementing a Custom Strategy

  1. Class Definition:

    • Your strategy class must be named Strategy and extend the BaseStrategy class.

    • Here's a basic example of a custom strategy implementation:

    from ats.strategies.base_strategy import BaseStrategy
    from ats.exchanges.data_classes.candle import Candle
    
    class Strategy(BaseStrategy):
        def validate_config(self) -> None:
            """
            Validates the strategy-specific configuration.
            Raise an exception if any required config is missing or invalid.
            """
            if "required_key" not in self.config:
                raise ValueError("Missing required configuration: 'required_key'")
            # Add additional validation logic here.
    
        def on_candle(self, candle: Candle) -> None:
            """
            Implements the core logic of the strategy.
            This method is triggered whenever a new candle is received.
            Args:
                candle: The received Candle object.
    
            Returns:
                None
            """
            # Example strategy logic: Print the candle close price
            print(f"Received candle close price: {candle.close}")
    
        def on_stop(self) -> None:
            """
            Logic to execute when the strategy is stopped.
            This can include cleaning up resources or saving states.
            """
            print("Strategy stopped.")
  2. Requirements:

    • Ensure your class implements the following abstract methods from BaseStrategy:

      • validate_config(): Validates the configuration provided for the strategy.

      • on_candle(candle: Candle): Defines the main logic for processing incoming candle data.

    • Optionally, you can override the following methods from BaseStrategy:

      • on_stop(): Called when the strategy is stopped. This method can be used to clean up resources or save the state.

  3. States and Configuration:

    • Use the state object (SimpleState) to manage the internal state of the strategy. This ensures that the strategy's state can be saved and restored, enabling seamless restarts.

    • Validate all required configurations in the validate_config() method to ensure that the strategy has everything it needs to function correctly.

  4. Setting the Exchange:

    • The set_exchange(exchange: BaseExchange) method will be called by the trading job to associate the strategy with an exchange. You don’t need to implement this method unless additional logic is required.

Accessing Exchange from the Strategy

Once the exchange is set using the set_exchange() method, you can interact with the exchange through the self.exchange object. This allows you to:

  • Place and manage orders

  • Fetch wallet balances

  • Access other exchange-specific functionalities

For example:

# Placing an order through the exchange
order = self.exchange.submit_order(order_details)

Configuration Validation

To ensure that your strategy functions correctly, all necessary configurations must be validated in the validate_config() method. Raise an exception if any required configuration key is missing or invalid.

Notes on Strategy Logic

  • Event Handling: The on_candle() method is where the main logic of the strategy resides. It is triggered whenever a new candle is received from the exchange.

  • State Management: Use the self._state object to store key-value pairs representing the strategy's state. This enables saving and reloading the state when the strategy restarts.

  • Exchange Interaction: After the exchange is set using set_exchange(), you can interact with the exchange through the self.exchange object for placing orders, retrieving balances, etc.

Last updated