Developer DocumentationΒΆ
This documentation is intended for developers who want to extend the infinity-grid trading bot with new exchanges, strategies, or other functionality. It provides guidance on the architecture, interfaces, and best practices for contributing to the project.
ποΈ Architecture OverviewΒΆ
The infinity-grid trading bot follows a modular architecture with clear separation of concerns:
Core Components: State machine, engine, event bus, and other foundational elements.
Interfaces: Well-defined contracts for exchange operations, notifications, etc.
Models: Data structures representing configurations, orders, balances, etc.
Adapters: Implementations of interfaces for specific exchanges or services.
Strategies: Trading algorithms that use the adapters to execute trades.
Services: Supporting functionality like database access and notifications.
Infrastructure: Low-level components like database management.
π©» Project StructureΒΆ
infinity_grid/
βββ exceptions.py
βββ adapters/ # Implementations of interfaces
β βββ exchanges/ # Exchange-specific adapters
β β βββ kraken.py # Kraken exchange adapter
β βββ notification.py # Notification service adapters
βββ core/ # Core functionality
β βββ cli.py # Command-line interface
β βββ engine.py # The main engine driving the algorithm
β βββ event_bus.py # Event management
β βββ state_machine.py # Bot state management
βββ infrastructure/ # Low-level components
β βββ database.py # Database schemas and access
βββ interfaces/ # Interface definitions
β βββ exchange.py # Exchange interface
β βββ notification.py # Notification interface
βββ models/ # Data models
β βββ configuration.py # Configuration models
β βββ exchange.py # Exchange-related models
βββ services/ # Supporting services
β βββ database.py # Database service
β βββ notification.py # Notification service
βββ strategies/ # Trading strategies
βββ grid_base.py # Base grid strategy
βββ grid_hodl.py # HODL grid strategy
βββ grid_sell.py # Sell grid strategy
βββ c_dca.py # Dollar-cost averaging strategy
βββ swing.py # Swing trading strategy
π§© Extension PointsΒΆ
The infinity-grid bot is designed to be extended in several ways:
Adding New Exchanges: Implement the exchange interfaces to support additional trading platforms.
Creating New Strategies: Extend the base strategy classes to implement new trading algorithms.
Custom Notifications: Extend the notification adapters for different notification channels.
Enhanced Monitoring: Add new metrics or monitoring capabilities.
π Adding a New Exchange AdapterΒΆ
To add support for a new exchange, you need to create an adapter that implements both the REST and WebSocket interfaces:
Create a new file in
infinity_grid/adapters/exchanges/named after the exchange (e.g.,binance.py)Implement the REST interface by creating a class that inherits from
infinity_grid.interfaces.exchange.IExchangeRESTServiceImplement the WebSocket interface by creating a class that inherits from
infinity_grid.interfaces.exchange.IExchangeWebSocketServiceDefine the exchange domain by creating an instance of
infinity_grid.models.exchange.ExchangeDomainwith the exchangeβs specific naming conventionsAdapt to exchange-specific behavior by ensuring that the implemented interfaces behave as expected. Feel free to orientate on existing adapters.
from infinity_grid.interfaces.exchange import IExchangeRESTService, IExchangeWebSocketService
from infinity_grid.models.exchange import ExchangeDomain
# Define exchange-specific constants
NEW_EXCHANGE_DOMAIN = ExchangeDomain(
EXCHANGE="NewExchange",
BUY="buy",
SELL="sell",
OPEN="open",
CLOSED="closed",
CANCELED="canceled",
EXPIRED="expired",
PENDING="pending",
)
class NewExchangeRESTService(IExchangeRESTService):
"""Implementation of the REST interface for NewExchange"""
def __init__(self, api_public_key, api_secret_key, state_machine, base_currency, quote_currency):
# Initialize the REST client
# Set up any exchange-specific configuration
def check_api_key_permissions(self):
# Implement permission checking logic
# Implement all other required methods from IExchangeRESTService
class NewExchangeWebSocketService(IExchangeWebSocketService):
"""Implementation of the WebSocket interface for NewExchange"""
def __init__(self, api_public_key, api_secret_key, state_machine, event_bus):
# Initialize the WebSocket client
# Set up event handlers
# Implement all required methods from IExchangeWebSocketService
π Creating a New Trading StrategyΒΆ
To create a new trading strategy, you should extend one of the existing base strategies or create a completely new one:
Create a new file in
infinity_grid/strategies/named after your strategy (e.g.,my_strategy.py)Extend an appropriate base class such as
infinity_grid.strategies.grid_base.GridStrategyBasefor grid-based strategiesImplement the required methods based on your trading logic
Use the state machine to manage the strategyβs state transitions
Handle events using the event bus for asynchronous operations
from infinity_grid.strategies.grid_base import GridStrategyBase
from infinity_grid.core.state_machine import States
from infinity_grid.exceptions import BotStateError
class MyCustomStrategy(GridStrategyBase):
"""This is a new sample strategy, based on the GridStrategyBase
NOTE: When deviating from grid-like trading, make sure to mock, disable,
or overwrite all functions of the GridStrategyBase.
"""
async def run(self):
"""Main entry point for the strategy"""
try:
# Initialize strategy-specific components
await self._initialize()
# Start trading
await self._start_trading()
except Exception as exc:
self._state_machine.transition_to(States.ERROR)
raise BotStateError("Strategy initialization failed") from exc
async def _initialize(self):
"""Initialize strategy-specific components"""
# Implement initialization logic
async def _start_trading(self):
"""Start the trading process"""
# Implement trading logic
# Implement other strategy-specific methods
π Testing Your ExtensionsΒΆ
When developing new adapters or strategies, itβs important to test them thoroughly:
Unit Tests: Create unit tests in the
tests/unit/directory to test your implementations.Integration Tests: Add integration tests in
tests/integration/for end-to-end testing.Mocking: Use mocking to simulate exchange responses without making actual API calls.
π€ State Machine and Error HandlingΒΆ
The infinity-grid uses a state machine that must be used for transitioning to states. It allows the algorithm to determine the current state and perform actions on that, e.g. not placing orders during the initialization or when being in an error state.
When developing on the infinity-grid, the transition to the desired state can be
achieved as demonstrated below. Additionally, the BotStateError must be
raised in order to exit the current context.
try:
...
except Exception as exc:
self.__state_machine.transition_to(States.ERROR)
raise BotStateError("Ooops!") from exc
- class infinity_grid.core.state_machine.States(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)ΒΆ
Bases:
EnumRepresents the state of the trading bot
- ERROR = 4ΒΆ
The algorithm encountered an error and is handling it.
- INITIALIZING = 1ΒΆ
The algorithm is initializing from the beginning.
- RUNNING = 2ΒΆ
The algorithm is running.
- SHUTDOWN_REQUESTED = 3ΒΆ
A request to shutdown is being processed.
π°οΈ Exchange InterfacesΒΆ
Exchange adapters must implement all functions of the listed interfaces in order to work properly. Please also read the docstrings of required functions carefully to avoid errors and misbehavior.
π¬ StrategiesΒΆ
ποΈ Models and SchemasΒΆ
π©Ή ExceptionsΒΆ
Custom exceptions for the Infinity Grid trading bot.
- exception infinity_grid.exceptions.BotStateErrorΒΆ
Custom exception for terminating the algorithm due to an error state.
This exception must only be raised in functions within the running loop, that would otherwise continue running or returning something time before the algorithm is terminating due to an error state.
- messageΒΆ
The error message to be displayed.
- Type:
str
Example:
def func(): try: do_something() except Exception as exc: message = "Exception while processing message." LOG.error(msg=message, exc_info=exc) self.state_machine.transition_to(States.ERROR) raise GridBotErrorState(message) from exc
- exception infinity_grid.exceptions.MetricsServerErrorΒΆ
Custom exception for metrics server related errors.
This exception is raised when the metrics server encounters errors during startup, shutdown, or request handling.
- messageΒΆ
The error message describing what went wrong.
- Type:
str
Example:
try: await metrics_server.start() except Exception as exc: raise MetricsServerError("Failed to start metrics server") from exc
- exception infinity_grid.exceptions.UnknownOrderErrorΒΆ
Exception used to be raised when an order that was requested is unknown.