Skip to content

Advanced Topics

This guide covers advanced concepts and techniques for developing sophisticated trading bots with Traderion.

Current and Upcoming Features

The Traderion framework currently provides core functionality for building trading bots with technical analysis strategies and basic position management. This page includes both currently implemented features and templates for future extensions you can implement yourself.

graph TD
    A[TraderionBot] --> B[Event Handlers]
    A --> C[Strategy Manager]
    A -.-> D[Risk Manager]
    A -.-> E[Performance Monitor]

    C --> F[Technical Strategies]
    C --> G[Client Strategies]
    C --> H[Custom Strategies]

    F --> I[EMA]
    F --> J[MACD]
    F --> K[RSI]
    F -.-> L[Custom Indicators]

    D -.-> M[Position Limits]
    D -.-> N[Stop Loss]
    D -.-> O[Take Profit]
    D -.-> P[Dynamic Sizing]

    E -.-> Q[Metrics Collection]
    E -.-> R[Reporting]
    E -.-> S[Alerting]

    style A fill:#d4f1f9,stroke:#333,stroke-width:2px
    style C fill:#d5e8d4,stroke:#333
    style D fill:#ffe6cc,stroke:#333,stroke-dasharray: 5 5
    style E fill:#f8cecc,stroke:#333,stroke-dasharray: 5 5
    style L fill:#d5e8d4,stroke:#333,stroke-dasharray: 5 5
    style M fill:#ffe6cc,stroke:#333,stroke-dasharray: 5 5
    style N fill:#ffe6cc,stroke:#333,stroke-dasharray: 5 5
    style O fill:#ffe6cc,stroke:#333,stroke-dasharray: 5 5
    style P fill:#ffe6cc,stroke:#333,stroke-dasharray: 5 5
    style Q fill:#f8cecc,stroke:#333,stroke-dasharray: 5 5
    style R fill:#f8cecc,stroke:#333,stroke-dasharray: 5 5
    style S fill:#f8cecc,stroke:#333,stroke-dasharray: 5 5

    classDef upcoming stroke-dasharray: 5 5;
    linkStyle 2,3,7,8,9,10,11,12,13,14,15 stroke-dasharray: 5 5;

Note: Dashed lines indicate upcoming/template features that are not yet fully implemented in the core framework.

Custom Technical Indicators (Template)

The following is a template for creating your own technical indicators to implement unique trading strategies:

class CustomIndicator:
    """
    A template for creating custom technical indicators.

    This example implements a weighted moving average with more
    weight given to recent prices.
    """
    def __init__(self, period, weight_factor=0.1):
        self.period = period
        self.weight_factor = weight_factor
        self.values = []
        self.current_value = None

    def update(self, price):
        # Add new price to values
        self.values.append(price)

        # Keep only the most recent 'period' values
        if len(self.values) > self.period:
            self.values.pop(0)

        # Calculate weighted average
        weights = [(1 + self.weight_factor * i) for i in range(len(self.values))]
        total_weight = sum(weights)

        self.current_value = sum(p * w for p, w in zip(self.values, weights)) / total_weight
        return self.current_value

    def get_value(self):
        return self.current_value

Implementing in a Bot

class AdvancedBot(TraderionBot):
    def __init__(self, username, password, room_id):
        super().__init__(username, password, room_id)
        self.wma = CustomIndicator(period=14, weight_factor=0.2)
        self.price_history = []

    def on_price_curve_change(self, old_price_curve, new_price_curve):
        # Extract prices from price curve
        prices = [price for (_, price) in new_price_curve]
        self.price_history = prices

        # Update indicator with latest price
        latest_price = prices[-1] if prices else None
        if latest_price:
            indicator_value = self.wma.update(latest_price)
            print(f"Latest price: {latest_price}, WMA: {indicator_value}")

    def main_loop(self):
        if not self.price_history:
            return

        current_price = self.price_history[-1]
        indicator_value = self.wma.get_value()

        if current_price > indicator_value * 1.02:  # 2% above WMA
            # Consider selling
            print("Sell signal generated")
        elif current_price < indicator_value * 0.98:  # 2% below WMA
            # Consider buying
            print("Buy signal generated")

Advanced Strategy Composition (Template)

The following is a template for combining multiple strategies with weighted decision-making:

class StrategyManager:
    def __init__(self, api):
        self.api = api
        self.strategies = {}
        self.weights = {}

    def add_strategy(self, name, strategy, weight=1.0):
        """Add a strategy with an optional weight."""
        self.strategies[name] = strategy
        self.weights[name] = weight

    def get_decision(self):
        """
        Get a weighted decision from all strategies.
        Returns a value between -1 (strong sell) and 1 (strong buy).
        """
        if not self.strategies:
            return 0

        total_weight = sum(self.weights.values())
        weighted_decision = 0

        for name, strategy in self.strategies.items():
            # Get strategy signal (-1 to 1)
            signal = strategy.get_signal()

            # Apply weight
            weight = self.weights[name] / total_weight
            weighted_decision += signal * weight

        return weighted_decision

    def execute(self):
        """Execute trades based on the weighted decision."""
        decision = self.get_decision()

        # Strong signals (above 0.7 or below -0.7)
        if decision > 0.7:
            # Strong buy signal
            self.execute_buy(size="large")
        elif decision > 0.3:
            # Moderate buy signal
            self.execute_buy(size="medium")
        elif decision > 0.1:
            # Weak buy signal
            self.execute_buy(size="small")
        elif decision < -0.7:
            # Strong sell signal
            self.execute_sell(size="large")
        elif decision < -0.3:
            # Moderate sell signal
            self.execute_sell(size="medium")
        elif decision < -0.1:
            # Weak sell signal
            self.execute_sell(size="small")
        # Otherwise hold

Implementation Example

class CompositeBot(TraderionBot):
    def __init__(self, username, password, room_id):
        super().__init__(username, password, room_id)

        # Create strategy manager
        self.manager = StrategyManager(self.api)

        # Add strategies with weights
        self.manager.add_strategy("ema", CrossingEMAs(self.api, {
            'target_amount': 10000, 
            'small_ema_period': 5, 
            'big_ema_period': 20
        }), weight=1.5)  # Higher weight for EMA

        self.manager.add_strategy("rsi", Rsi(self.api, {
            'target_amount': 10000, 
            'period': 14, 
            'overbought_threshold': 70, 
            'oversold_threshold': 30
        }), weight=1.0)

        self.manager.add_strategy("macd", Macd(self.api, {
            'target_amount': 10000, 
            'small_ema_period': 12, 
            'big_ema_period': 26, 
            'signal_ema_period': 9
        }), weight=1.2)

    def main_loop(self):
        # Let the strategy manager make decisions
        self.manager.execute()

Advanced Risk Management (Template)

The following is a template for implementing sophisticated risk management techniques:

class RiskManager:
    def __init__(self, api, config):
        self.api = api

        # Configuration
        self.max_position = config.get('max_position', 50000)
        self.max_drawdown = config.get('max_drawdown', 0.05)  # 5%
        self.stop_loss_pct = config.get('stop_loss', 0.02)    # 2%
        self.take_profit_pct = config.get('take_profit', 0.03)  # 3%

        # State
        self.entry_prices = {}  # Track entry prices for positions
        self.position_sizes = {}  # Track position sizes

    def check_stop_loss(self, position):
        """Check if stop loss has been triggered."""
        if position['amount'] == 0:
            return False

        direction = 1 if position['amount'] > 0 else -1
        entry_price = self.entry_prices.get(direction, position['rate'])
        current_price = self.api.get_market_prices()

        if direction > 0:  # Long position
            stop_price = entry_price * (1 - self.stop_loss_pct)
            return current_price['bid'] <= stop_price
        else:  # Short position
            stop_price = entry_price * (1 + self.stop_loss_pct)
            return current_price['ask'] >= stop_price

    def check_take_profit(self, position):
        """Check if take profit has been triggered."""
        if position['amount'] == 0:
            return False

        direction = 1 if position['amount'] > 0 else -1
        entry_price = self.entry_prices.get(direction, position['rate'])
        current_price = self.api.get_market_prices()

        if direction > 0:  # Long position
            take_profit_price = entry_price * (1 + self.take_profit_pct)
            return current_price['bid'] >= take_profit_price
        else:  # Short position
            take_profit_price = entry_price * (1 - self.take_profit_pct)
            return current_price['ask'] <= take_profit_price

    def check_drawdown(self, position):
        """Check if maximum drawdown has been exceeded."""
        return position['pnl_percentage'] < -self.max_drawdown

    def manage_risk(self):
        """Main risk management function."""
        position = self.api.get_position()

        # Check stop loss
        if self.check_stop_loss(position):
            print("Stop loss triggered")
            self.close_position(position)
            return True

        # Check take profit
        if self.check_take_profit(position):
            print("Take profit triggered")
            self.close_position(position)
            return True

        # Check drawdown
        if self.check_drawdown(position):
            print("Maximum drawdown exceeded")
            self.reduce_position(position, reduction_pct=0.5)
            return True

        return False

    def close_position(self, position):
        """Close the current position."""
        if position['amount'] == 0:
            return

        direction = 0 if position['amount'] > 0 else 1  # Opposite direction to close
        amount = abs(position['amount']) / self.api.ticket_unit  # Convert to short amount

        # Execute the trade to close position
        depth = self.api.get_eb_depth()
        self.api.hit_price(direction, amount, depth[direction][0]['price'])

    def reduce_position(self, position, reduction_pct=0.5):
        """Reduce the current position by a percentage."""
        if position['amount'] == 0:
            return

        direction = 0 if position['amount'] > 0 else 1  # Opposite direction to reduce
        amount = abs(position['amount']) * reduction_pct / self.api.ticket_unit  # Convert to short amount

        # Execute the trade to reduce position
        depth = self.api.get_eb_depth()
        self.api.hit_price(direction, amount, depth[direction][0]['price'])

    def on_new_position(self, direction, amount, price):
        """Track new positions."""
        self.entry_prices[direction] = price
        self.position_sizes[direction] = amount

Implementation in a Bot

class RiskManagedBot(TraderionBot):
    def __init__(self, username, password, room_id):
        super().__init__(username, password, room_id)

        # Initialize risk manager
        self.risk_manager = RiskManager(self.api, {
            'max_position': 50000,
            'max_drawdown': 0.05,
            'stop_loss': 0.02,
            'take_profit': 0.03
        })

        # Initialize strategy
        self.strategy = CrossingEMAs(self.api, {
            'target_amount': 10000,
            'small_ema_period': 5,
            'big_ema_period': 20
        })

    def on_position_change(self, old_position, new_position):
        # Update risk manager with position changes
        if old_position['amount'] == 0 and new_position['amount'] != 0:
            # New position opened
            direction = 1 if new_position['amount'] > 0 else 0
            amount = abs(new_position['amount'])
            price = new_position['rate']
            self.risk_manager.on_new_position(direction, amount, price)

    def main_loop(self):
        # First check risk management rules
        if self.risk_manager.manage_risk():
            # If risk management took action, skip strategy execution
            return

        # Execute strategy if risk management didn't intervene
        self.strategy.run()

Next Steps