# 🧪 Test Plan: Backtest Runner Skill (Mastra Agent) **Цель:** Проверить стабильность, корректность загрузки данных и исполнения стратегий в изолированной среде Freqtrade (Docker). **Тестируемый инструмент:** `runBacktest` **Зависимости:** Docker, Santiment Data Service, Freqtrade Image. --- ## 🛠 Предварительные требования (Prerequisites) 1. **Environment:** Локально запущенный Docker Desktop. 2. **Config:** Заполненный `.env` (доступ к SanR/Santiment API). 3. **State:** В рамках теста в "памяти" агента (или в файловой системе песочницы) должны существовать файлы `strategy.py` и `config.json`. --- ## 1. Функциональное тестирование: Базовая механика и Даты Эти тесты проверяют, что инфраструктура работает, а данные корректно загружаются для разных эпох рынка. ### ✅ Тест-кейс 1.1: Исторический прогон (Deep History) * **Описание:** Запуск простой стратегии на данных 2-3 летней давности. * **Цель:** Убедиться, что API Santiment отдает архивные данные и Freqtrade корректно их обрабатывает. * **Входные данные:** * **Стратегия:** `SimpleStrategy` (покупка RSI < 30, продажа RSI > 70). * **Пара:** `BTC/USDT:USDT` (Фьючерсы). * **Таймфрейм:** `1d`. * **Timerange:** `20210101-20210201` (Январь 2021). * **Ожидаемый результат:** 1. Инструмент возвращает `success: true`. 2. В логах нет ошибок `No data found`. 3. `Total Trades` > 0 (так как волатильность была высокой). 4. Графики и сделки соответствуют ценам 2021 года (30k-40k$). ### ✅ Тест-кейс 1.2: Свежий прогон + Граничный случай (Single Day) * **Описание:** Запуск теста за "вчера" или за один конкретный день. * **Цель:** Проверить наличие свежих данных и работу механизма автоматического расширения дат (фикс проблемы "пустого бэктеста"). * **Входные данные:** * **Стратегия:** `SimpleStrategy`. * **Timerange:** `YYYYMMDD-YYYYMMDD` (где дата начала равна дате конца, например `20241201-20241201`). * **Ожидаемый результат:** 1. Система **автоматически** расширяет диапазон до +1 дня (в логах агента видно предупреждение/фикс). 2. Freqtrade успешно запускается и прогоняет 24 свечи (для 1h) или 288 (для 5m). 3. Результат `success: true`. --- ## 2. Логическое тестирование: Копитрейдинг (Copy Trading) Самый важный блок. Проверяем, что сигналы превращаются в реальные сделки. ### ✅ Тест-кейс 2.1: Верификация входа в сделку (Signal Execution) * **Описание:** Проверка стратегии, использующей `sdk.py` для копирования сигналов конкретного трейдера. * **Подготовка:** Найти в SanR трейдера (например, `semaca` или `brian`), у которого **точно** был сигнал в выбранный период. * **Входные данные:** * **Стратегия:** `CopyTradeStrategy`. Логика: ```python # Pseudo-code if signal['direction'] == 'up': return enter_long if signal['direction'] == 'down': return enter_short ``` * **Конфиг:** Включенная пара, по которой был сигнал (например, `ETH/USDT:USDT`). * **Timerange:** Период, охватывающий этот сигнал. * **Ожидаемый результат:** 1. `prepareMarketData` загружает данные для пары. 2. В логах стратегии (через `logger.info`) видно: "Received signal UP for ETH". 3. **Критично:** В таблице результатов Freqtrade `Total Trades` >= 1. 4. Время входа в сделку в отчете совпадает (с точностью до свечи) со временем сигнала в SanR. --- ## 3. Негативное тестирование и Обработка ошибок (Resilience) Проверяем, как система ведет себя при сбоях. ### ✅ Тест-кейс 3.1: Runtime-ошибка в коде (Crash Test) * **Описание:** Запуск стратегии с валидным синтаксисом, но ошибкой выполнения. * **Входные данные:** * **Стратегия:** В методе `populate_indicators` добавить `x = 1 / 0`. * **Timerange:** Любой валидный. * **Ожидаемый результат:** 1. Агент **не падает**. 2. Инструмент возвращает `success: false` (или `true` с текстом ошибки, зависит от реализации парсера). 3. В поле `error` или `logTail` содержится Python Traceback: `ZeroDivisionError: division by zero`. 4. Пользователю выводится понятное сообщение: "Произошла ошибка в коде стратегии...". ### ✅ Тест-кейс 3.2: Отсутствующие рыночные данные (Invalid Pair) * **Описание:** Попытка запустить тест на несуществующей или делистинговой монете. * **Входные данные:** * **Config:** `pair_whitelist: ["SCAMTOKEN/USDT:USDT"]`. * **Timerange:** Любой. * **Ожидаемый результат:** 1. Бэктест **не начинается** (Docker не запускается). 2. Ошибка отлавливается на этапе `prepareMarketData`. 3. Сообщение об ошибке: `Missing slugs for pairs...` или `Data fetch failed`. --- ## 4. Чек-лист для ручного тестирования (Manual QA) Если автоматические тесты прошли, тестировщик должен проверить UX в диалоге с агентом: 1. [ ] Попросить агента: *"Протестируй стратегию за 2022 год"*. Агент должен сам сконвертировать это в формат `20220101-20221231`. 2. [ ] Попросить: *"Протестируй за последнюю неделю"*. Проверить, что даты корректны. 3. [ ] После успешного теста спросить: *"Какой был максимальный просад (drawdown)?"*. Агент должен прочитать это из логов (используя навык `backtest-reporter`). --- ## Пример кода для запуска Copy Trading теста (для разработчика) Этот код можно использовать в `scenarios.spec.ts` для Тест-кейса 2.1: ```typescript it('Copy Trading: should open a trade when signal is present', async () => { // 1. Setup Strategy that mimics Copy Trading logic const copyStrategy = ` class Strategy(IStrategy): def populate_indicators(self, dataframe, metadata): # MOCK SIGNAL: Force a buy signal on specific date dataframe['enter_long'] = 0 dataframe.loc[dataframe['date'] == '2024-01-15 12:00:00+00:00', 'enter_long'] = 1 return dataframe # ... rest of required methods `; // 2. Run Test around that date await setupArtifacts(copyStrategy, 'ETH/USDT:USDT'); const result = await runBacktest.execute({ timerange: '20240114-20240116' }); // 3. Assertions expect(result.success).toBe(true); // Проверяем, что сделка реально открылась expect(result.logTail).toMatch(/Total Trades\s+\|\s+1/); expect(result.logTail).toMatch(/Win Rate\s+\|\s+100%|0%/); // Сделка должна быть закрыта }); ```