Вы когда-нибудь видели, как очередной гений из Twitter хвастается графиком доходности своего AI-трейдера? Показывает красивую кривую, которая растет ровно вверх, и обещает поделиться секретом за $999. А вы думаете: "Интересно, а на реальных деньгах это тоже работает? Или он просто переобучил модель на исторических данных?"
Проблема в том, что проверить это невозможно. Точнее, было невозможно. Пока вы не начнете тестировать стратегии в условиях, максимально приближенных к реальным, но без риска потерять деньги. Именно для этого нужен симулятор.
Главная ошибка новичков в алгоритмическом трейдинге - тестировать стратегии на исторических данных без учета спреда, комиссий и ликвидности. В симуляторе вы проигрываете виртуальные деньги. В реальности - настоящие.
Зачем вообще симулятор, если есть бэктесты?
Отличный вопрос. Бэктестинг - это когда вы прогоняете стратегию по историческим данным. Симулятор - когда вы запускаете стратегию "вживую", но на виртуальные деньги, используя реальные котировки в реальном времени.
Разница как между просмотром записи футбольного матча и игрой в футбол. В записи вы видите результат. В реальной игре - испытываете давление, принимаете решения в условиях неопределенности, ошибаетесь.
- Бэктест: "Моя стратегия заработала бы 150% за 2024 год"
- Симулятор: "Моя стратегия потеряла 30% виртуальных денег за первую неделю, потому что я не учел комиссию на частые сделки"
Второй вариант полезнее. Намного.
Архитектура: из чего состоит ArenaGo
Представьте, что вы строите гоночный симулятор. Вам нужна трасса (рыночные данные), машина (торговая стратегия), физический движок (исполнение сделок) и приборная панель (мониторинг).
Вот как это выглядит в коде:
# core/architecture.py
class TradingArena:
"""
Главный класс симулятора.
Соединяет все компоненты в работающую систему.
"""
def __init__(self):
self.data_feed = MarketDataFeed() # Источник котировок
self.execution_engine = ExecutionEngine() # Исполнение сделок
self.portfolio = Portfolio() # Виртуальный портфель
self.strategy = None # AI-стратегия (подключается)
self.metrics = PerformanceMetrics() # Сбор статистики
def run(self, days: int):
"""Запускает симуляцию на N торговых дней"""
for day in range(days):
# Получаем новые данные
market_data = self.data_feed.get_next()
# Стратегия принимает решение
decision = self.strategy.decide(market_data)
# Исполняем сделку (если нужно)
if decision:
self.execution_engine.execute(
decision,
self.portfolio
)
# Обновляем метрики
self.metrics.update(self.portfolio)
1 Где брать реальные котировки (бесплатно)
Первый вопрос, который всех волнует. На 2026 год есть несколько проверенных вариантов:
| Источник | Что дает | Лимиты | Стоимость |
|---|---|---|---|
| Alpha Vantage | Исторические данные, индикаторы | 5 запросов/мин, 500/день | Бесплатно (с лимитами) |
| Twelve Data | Реалтайм, Forex, крипта | 800 запросов/день | Бесплатный тариф |
| Yahoo Finance | Исторические данные (yfinance) | Неограниченно | Полностью бесплатно |
| Polygon.io | Агрегированные тики, реальное время | 5 запросов/мин на бесплатном | Бесплатно (базовый) |
Для симулятора я рекомендую комбинацию: Yahoo Finance для загрузки истории + Twelve Data для симуляции реального времени. Почему? Yahoo дает данные бесплатно и без ограничений (через библиотеку yfinance), а Twelve Data имеет хороший бесплатный лимит и WebSocket для реального времени.
# data/yahoo_source.py
import yfinance as yf
import pandas as pd
class YahooDataFeed:
"""Загрузка исторических данных с Yahoo Finance"""
def __init__(self, ticker: str, period: str = "1y"):
self.ticker = ticker
self.period = period
def load(self) -> pd.DataFrame:
"""Загружает OHLCV данные"""
stock = yf.Ticker(self.ticker)
df = stock.history(period=self.period)
# Добавляем расчетные поля
df['returns'] = df['Close'].pct_change()
df['volatility'] = df['returns'].rolling(20).std()
return df
Важный нюанс: Yahoo Finance иногда меняет структуру ответа. Всегда обновляйте yfinance до последней версии и добавляйте обработку ошибок. В 2025 была проблема с временными зонами - данные приходили со смещением на час.
2 Движок исполнения: как симулировать реальный трейдинг
Вот где большинство симуляторов отрываются от реальности. Они предполагают, что вы можете купить или продать по цене закрытия свечи. В реальном мире есть спред, комиссии, проскальзывание и ограниченная ликвидность.
Правильный движок исполнения должен учитывать:
- Спред: разница между ценой покупки и продажи
- Комиссия: биржа берет процент от сделки
- Проскальзывание: цена успевает измениться пока ваш ордер исполняется
- Лимиты объема: нельзя купить больше, чем есть в стакане
# execution/realistic_engine.py
class RealisticExecutionEngine:
"""Движок исполнения с реалистичными условиями"""
def __init__(self,
commission: float = 0.001, # 0.1%
spread: float = 0.0005, # 0.05%
slippage: float = 0.0002): # 0.02%
self.commission = commission
self.spread = spread
self.slippage = slippage
def execute(self,
signal: str, # 'BUY' или 'SELL'
price: float,
quantity: float,
portfolio: Portfolio) -> TradeResult:
"""Исполняет сделку с учетом всех издержек"""
# Корректируем цену на спред
if signal == 'BUY':
execution_price = price * (1 + self.spread)
else: # SELL
execution_price = price * (1 - self.spread)
# Добавляем проскальзывание (случайное)
slippage_effect = np.random.uniform(-self.slippage, self.slippage)
execution_price *= (1 + slippage_effect)
# Рассчитываем комиссию
trade_value = execution_price * quantity
commission_fee = trade_value * self.commission
# Общая стоимость сделки
total_cost = trade_value + commission_fee
# Обновляем портфель
if signal == 'BUY':
portfolio.cash -= total_cost
portfolio.positions[asset] += quantity
else:
portfolio.cash += (trade_value - commission_fee)
portfolio.positions[asset] -= quantity
return TradeResult(
price=execution_price,
commission=commission_fee,
slippage=slippage_effect
)
Звучит сложно? На самом деле, это базовая финансовая математика. Без этих расчетов ваш симулятор будет показывать завышенную доходность. Иногда на 20-30% завышенную. Представьте, что вы протестировали стратегию, она показала +50% в симуляторе. Запускаете на реальные деньги - а она едва выходит в ноль. Потому что комиссии съели всю прибыль.
3 AI-стратегия: от простого ML до RL-агента
Теперь самое интересное - мозги нашего трейдера. Здесь есть градация сложности:
- Правила на индикаторах: "Купить, когда RSI < 30, продать когда RSI > 70"
- Классический ML: Логистическая регрессия или градиентный бустинг для предсказания направления
- Временные ряды: LSTM или Transformer для предсказания цены
- Reinforcement Learning: Агент, который учится торговать через trial-and-error
Для начала рекомендую второй вариант. Почему? Потому что RL-агенты - это круто звучит, но на практике их обучать сложно, долго и нестабильно. Классический ML дает предсказуемый результат.
Вот минимальный рабочий пример:
# strategies/ml_strategy.py
from sklearn.ensemble import GradientBoostingClassifier
import numpy as np
class MLTradingStrategy:
"""Стратегия на основе градиентного бустинга"""
def __init__(self):
self.model = GradientBoostingClassifier(
n_estimators=100,
max_depth=3,
random_state=42
)
self.is_trained = False
def prepare_features(self, data: pd.DataFrame) -> np.array:
"""Готовит фичи из рыночных данных"""
features = []
# Простые технические индикаторы
data['sma_20'] = data['Close'].rolling(20).mean()
data['sma_50'] = data['Close'].rolling(50).mean()
data['rsi'] = self.calculate_rsi(data['Close'])
data['bb_upper'], data['bb_lower'] = self.bollinger_bands(data['Close'])
# Относительные изменения
data['returns_1d'] = data['Close'].pct_change(1)
data['returns_5d'] = data['Close'].pct_change(5)
# Объем
data['volume_sma'] = data['Volume'].rolling(20).mean()
data['volume_ratio'] = data['Volume'] / data['volume_sma']
# Убираем NaN
features_df = data.dropna()
return features_df[['sma_20', 'sma_50', 'rsi',
'bb_upper', 'bb_lower',
'returns_1d', 'returns_5d',
'volume_ratio']].values
def train(self, X: np.array, y: np.array):
"""Обучает модель на исторических данных"""
# y - целевая переменная: 1 если цена вырастет, 0 если упадет
self.model.fit(X, y)
self.is_trained = True
def decide(self, current_features: np.array) -> str:
"""Принимает торговое решение"""
if not self.is_trained:
return 'HOLD' # Не торговать, если модель не обучена
prediction = self.model.predict(current_features.reshape(1, -1))
probability = self.model.predict_proba(current_features.reshape(1, -1))
# Торгуем только если уверенность высокая
if prediction[0] == 1 and probability[0][1] > 0.65:
return 'BUY'
elif prediction[0] == 0 and probability[0][0] > 0.65:
return 'SELL'
else:
return 'HOLD'
Если хотите пойти дальше, посмотрите на CodeAct - агента, который пишет и исполняет торговый код. Или изучите Real-Time Bidding репозиторий с RL-агентами - там много пересекающихся идей.
4 API слой: как сделать симулятор доступным
Вы построили крутой симулятор. Теперь нужно дать к нему доступ. Вариантов несколько:
- Локальный скрипт: Запускаете Python файл, смотрите результаты в консоли
- Jupyter Notebook: Интерактивная среда с графиками
- REST API: Можно запускать симуляции через HTTP запросы
- Web интерфейс: Красивые графики, кнопки, слайдеры
Для ArenaGo я выбрал комбинацию REST API + простой фронтенд. Почему? Потому что это позволяет:
- Интегрировать симулятор в другие системы
- Запускать симуляции удаленно
- Строить дашборды на любой платформе
- Делиться доступом с командой
Вот минимальный FastAPI сервер:
# api/server.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uvicorn
app = FastAPI(title="ArenaGo Trading Simulator API")
# Глобальный объект симулятора (в продакшене нужно иначе)
simulator = None
class SimulationRequest(BaseModel):
ticker: str
strategy: str
initial_capital: float = 10000.0
days: int = 30
class SimulationResponse(BaseModel):
simulation_id: str
final_portfolio: float
sharpe_ratio: float
max_drawdown: float
trades_count: int
@app.post("/simulate", response_model=SimulationResponse)
def run_simulation(request: SimulationRequest):
"""Запускает новую симуляцию"""
try:
# Инициализируем симулятор с заданными параметрами
simulator = TradingArena(
ticker=request.ticker,
initial_capital=request.initial_capital
)
# Загружаем выбранную стратегию
if request.strategy == "ml_basic":
simulator.strategy = MLTradingStrategy()
elif request.strategy == "rsi_simple":
simulator.strategy = RSITradingStrategy()
else:
raise HTTPException(status_code=400,
detail=f"Unknown strategy: {request.strategy}")
# Запускаем симуляцию
results = simulator.run(days=request.days)
# Возвращаем результаты
return SimulationResponse(
simulation_id=generate_id(),
final_portfolio=results['final_value'],
sharpe_ratio=results['sharpe'],
max_drawdown=results['max_drawdown'],
trades_count=results['trades']
)
except Exception as e:
raise HTTPException(status_code=500,
detail=f"Simulation failed: {str(e)}")
@app.get("/results/{simulation_id}")
def get_results(simulation_id: str):
"""Возвращает детальные результаты симуляции"""
# Здесь логика загрузки из БД или кэша
pass
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Теперь вы можете запускать симуляции командой:
curl -X POST "http://localhost:8000/simulate" \
-H "Content-Type: application/json" \
-d '{"ticker":"AAPL", "strategy":"ml_basic", "days":90}'
Что чаще всего ломается (и как это чинить)
За 3 года работы с такими системами я собрал коллекцию самых частых проблем:
| Проблема | Симптомы | Решение |
|---|---|---|
| Look-ahead bias | Стратегия показывает нереальную доходность | Разделять данные на train/test по времени, никогда не использовать будущие данные для текущего решения |
| Overfitting | На исторических данных работает идеально, на новых - ужасно | Упрощать модели, использовать кросс-валидацию во времени, добавлять регуляризацию |
| Синхронизация времени | Сделки исполняются по "прошлым" ценам | Использовать временные метки с наносекундной точностью, учитывать задержки API |
| Утечка памяти | Симулятор замедляется со временем | Очищать исторические данные, использовать генераторы вместо списков, мониторить memory_profiler |
| API лимиты | Источник данных блокирует запросы | Добавлять кэширование, использовать очереди запросов, иметь fallback источник |
От симулятора к продакшену: что меняется
Допустим, ваш симулятор стабильно показывает +15% годовых с просадкой не более 5%. Вы хотите запустить его на реальные деньги. Что нужно изменить?
Все.
Ну, почти все. Основные отличия:
- Брокерский API вместо симулятора: Подключаетесь к реальному брокеру (Interactive Brokers, Alpaca, Tinkoff API)
- Мониторинг и алерты: Система должна уведомлять вас о сбоях, необычной активности, превышении лимитов
- Риск-менеджмент: Лимиты на размер позиции, стоп-лоссы на уровне системы (не только в стратегии)
- Резервное копирование и откат: Возможность быстро остановить систему и откатить сделку при ошибке
- Логирование всего: Каждое решение, каждая сделка, каждый запрос к API
- Юридические аспекты: В зависимости от юрисдикции могут быть ограничения на алгоритмическую торговлю
Для продакшена рекомендую изучить гайд по production-ready AI агентам. Многие принципы пересекаются.
Никогда не запускайте на реальные деньги стратегию, которая не протестирована хотя бы на 100 разных рыночных сценариях в симуляторе. Никогда. Даже если она показывала +100% последние 3 месяца. Рынок имеет привычку менять режимы, и то, что работало вчера, завтра может слить весь депозит.
Что дальше? Эволюция ArenaGo
Базовый симулятор - это только начало. Дальше можно развивать систему в нескольких направлениях:
- Мультиагентная симуляция: Запустить 1000 AI-трейдеров с разными стратегиями и посмотреть, как они взаимодействуют
- Генерация стресс-сценариев: Искусственно создавать обвалы рынка, всплески волатильности, ликвидные кризисы
- Transfer learning: Обучить стратегию на одном активе, адаптировать для другого
- Explainable AI: Не просто "купить", а "купить, потому что RSI показал перепроданность при росте объема"
- Интеграция с новостями: Анализ финансовых новостей и твитов для принятия решений
Самый интересный путь, на мой взгляд - создание AI-компаньона с памятью, который не только торгует, но и учится на своих ошибках, запоминает, что работало в прошлом, и адаптируется к новым условиям.
Или построить что-то вроде BigCodeArena для трейдинга - платформу, где разные AI-модели соревнуются в торговле, а вы выбираете лучшую.
Главное - начать с простого. С симулятора, который работает на вашем ноутбуке. Который позволяет тестировать идеи без риска. Который показывает не красивую картинку для Twitter, а реальные проблемы вашей стратегии.
Потому что в трейдинге, как и в любом сложном деле, первый шаг к успеху - перестать обманывать себя. А ArenaGo помогает именно в этом.