Naposledy aktivní 2 days ago

uxname's Avatar uxname revidoval tento gist 2 days ago. Přejít na revizi

1 file changed, 120 insertions, 49 deletions

test ideas.md

@@ -1,64 +1,135 @@
1 - Отличный план. Вы правильно выделили два главных сценария (базовый и копитрейдинг). Чтобы покрытие было полным и гарантировало стабильность системы, я предлагаю дополнить их сценариями на обработку ошибок и граничные случаи.
1 + # 🧪 Test Plan: Backtest Runner Skill (Mastra Agent)
2 2
3 - Вот **Топ-5 идей для тестов `backtest-runner`**, отсортированные от базовых к сложным:
3 + **Цель:** Проверить стабильность, корректность загрузки данных и исполнения стратегий в изолированной среде Freqtrade (Docker).
4 + **Тестируемый инструмент:** `runBacktest`
5 + **Зависимости:** Docker, Santiment Data Service, Freqtrade Image.
4 6
5 - ### 1. "Smoke Test": Запуск примитивной стратегии (Infrastructure Check)
6 - **Суть:** Проверка всей цепочки без сложной логики. Стратегия должна быть максимально глупой (например, покупать на каждой четной свече и продавать на нечетной).
7 - * **Цель:** Убедиться, что Docker запускается, вольюмы монтируются, конфиг валиден, и Freqtrade в принципе способен завершить работу.
7 + ---
8 +
9 + ## 🛠 Предварительные требования (Prerequisites)
10 + 1. **Environment:** Локально запущенный Docker Desktop.
11 + 2. **Config:** Заполненный `.env` (доступ к SanR/Santiment API).
12 + 3. **State:** В рамках теста в "памяти" агента (или в файловой системе песочницы) должны существовать файлы `strategy.py` и `config.json`.
13 +
14 + ---
15 +
16 + ## 1. Функциональное тестирование: Базовая механика и Даты
17 +
18 + Эти тесты проверяют, что инфраструктура работает, а данные корректно загружаются для разных эпох рынка.
19 +
20 + ### ✅ Тест-кейс 1.1: Исторический прогон (Deep History)
21 + * **Описание:** Запуск простой стратегии на данных 2-3 летней давности.
22 + * **Цель:** Убедиться, что API Santiment отдает архивные данные и Freqtrade корректно их обрабатывает.
23 + * **Входные данные:**
24 + * **Стратегия:** `SimpleStrategy` (покупка RSI < 30, продажа RSI > 70).
25 + * **Пара:** `BTC/USDT:USDT` (Фьючерсы).
26 + * **Таймфрейм:** `1d`.
27 + * **Timerange:** `20210101-20210201` (Январь 2021).
8 28 * **Ожидаемый результат:**
9 - * Инструмент возвращает `success: true`.
10 - * В логах (`logTail`) присутствует фраза `Backtesting finished`.
11 - * В результатах есть хотя бы одна сделка.
12 -
13 - ### 2. "Data Fetcher Test": Копитрейдинг с реальными данными (SanR Integration)
14 - **Суть:** Тест стратегии, которая импортирует `sdk.py` и запрашивает сигналы для реального пользователя (например, `semaca`) и реальной пары (`BTC/USDT:USDT`).
15 - * **Цель:** Проверить работу `prepareMarketData`. Это самое узкое место. Тест должен убедиться, что:
16 - 1. Система парсит конфиг и находит нужные пары.
17 - 2. Делает запрос к SanR API / Santiment API.
18 - 3. Скачивает JSON-файлы в `market_cache`.
19 - 4. Freqtrade внутри Docker видит эти данные.
20 - * **Ожидаемый результат:** Бэктест проходит успешно, не падает с ошибкой `No data found`.
21 -
22 - ### 3. "The One-Day Edge Case": Граничный случай с датами
23 - **Суть:** Запуск бэктеста, где дата начала равна дате конца (например, `timerange: "20241001-20241001"`).
24 - * **Почему это важно:** В вашем коде (`src/mastra/pro/tools/freqtrade.ts` и `tools.ts`) есть специальная логика, которая расширяет такой диапазон на +1 день. Если это сломается, Freqtrade загрузит 0 свечей и выдаст ошибку.
25 - * **Ожидаемый результат:** Система должна автоматически расширить диапазон до `20241002`, загрузить данные за сутки и провести тест (24 свечи на 1h таймфрейме).
26 -
27 - ### 4. "The Crash Test": Обработка Runtime-ошибки в Python
28 - **Суть:** Подсунуть стратегию с синтаксически верным кодом, но с логической ошибкой, которая вызовет краш во время выполнения (например, деление на ноль в `populate_indicators` или обращение к несуществующей колонке DataFrame).
29 - * **Цель:** Проверить, как `backtest-runner` обрабатывает падение контейнера или Python-исключения. Агент не должен падать сам, он должен вернуть лог с ошибкой.
29 + 1. Инструмент возвращает `success: true`.
30 + 2. В логах нет ошибок `No data found`.
31 + 3. `Total Trades` > 0 (так как волатильность была высокой).
32 + 4. Графики и сделки соответствуют ценам 2021 года (30k-40k$).
33 +
34 + ### ✅ Тест-кейс 1.2: Свежий прогон + Граничный случай (Single Day)
35 + * **Описание:** Запуск теста за "вчера" или за один конкретный день.
36 + * **Цель:** Проверить наличие свежих данных и работу механизма автоматического расширения дат (фикс проблемы "пустого бэктеста").
37 + * **Входные данные:**
38 + * **Стратегия:** `SimpleStrategy`.
39 + * **Timerange:** `YYYYMMDD-YYYYMMDD` (где дата начала равна дате конца, например `20241201-20241201`).
30 40 * **Ожидаемый результат:**
31 - * Инструмент возвращает `success: false` (или `true`, но с явным описанием ошибки в логах).
32 - * В `logTail` содержится Python Traceback (например, `ZeroDivisionError`).
41 + 1. Система **автоматически** расширяет диапазон до +1 дня (в логах агента видно предупреждение/фикс).
42 + 2. Freqtrade успешно запускается и прогоняет 24 свечи (для 1h) или 288 (для 5m).
43 + 3. Результат `success: true`.
44 +
45 + ---
33 46
34 - ### 5. "Missing Data Handling": Запрос несуществующей пары
35 - **Суть:** В конфиге указать пару, которой не существует на бирже или в Santiment (например, `NONEXISTENTCOIN/USDT:USDT`).
36 - * **Цель:** Проверить валидацию данных до запуска тяжелого Docker-контейнера.
47 + ## 2. Логическое тестирование: Копитрейдинг (Copy Trading)
48 +
49 + Самый важный блок. Проверяем, что сигналы превращаются в реальные сделки.
50 +
51 + ### ✅ Тест-кейс 2.1: Верификация входа в сделку (Signal Execution)
52 + * **Описание:** Проверка стратегии, использующей `sdk.py` для копирования сигналов конкретного трейдера.
53 + * **Подготовка:** Найти в SanR трейдера (например, `semaca` или `brian`), у которого **точно** был сигнал в выбранный период.
54 + * **Входные данные:**
55 + * **Стратегия:** `CopyTradeStrategy`. Логика:
56 + ```python
57 + # Pseudo-code
58 + if signal['direction'] == 'up': return enter_long
59 + if signal['direction'] == 'down': return enter_short
60 + ```
61 + * **Конфиг:** Включенная пара, по которой был сигнал (например, `ETH/USDT:USDT`).
62 + * **Timerange:** Период, охватывающий этот сигнал.
37 63 * **Ожидаемый результат:**
38 - * Инструмент должен выбросить ошибку на этапе `prepareMarketData`.
39 - * Ошибка должна быть понятной: "Missing slugs for pairs..." или "Failed to fetch data".
40 - * Docker запускаться **не должен** (экономия ресурсов).
64 + 1. `prepareMarketData` загружает данные для пары.
65 + 2. В логах стратегии (через `logger.info`) видно: "Received signal UP for ETH".
66 + 3. **Критично:** В таблице результатов Freqtrade `Total Trades` >= 1.
67 + 4. Время входа в сделку в отчете совпадает (с точностью до свечи) со временем сигнала в SanR.
41 68
42 69 ---
43 70
44 - ### Как это реализовать в коде (Пример для Vitest)
71 + ## 3. Негативное тестирование и Обработка ошибок (Resilience)
45 72
46 - Вы можете создать файл `src/mastra/super/skills/backtest-runner/scenarios.spec.ts` и реализовать эти сценарии, используя моки для `exec` (чтобы не ждать реальный докер долго) или реальные интеграционные тесты (как в примере 2).
73 + Проверяем, как система ведет себя при сбоях.
47 74
48 - **Пример структуры теста для кейса №1:**
75 + ### ✅ Тест-кейс 3.1: Runtime-ошибка в коде (Crash Test)
76 + * **Описание:** Запуск стратегии с валидным синтаксисом, но ошибкой выполнения.
77 + * **Входные данные:**
78 + * **Стратегия:** В методе `populate_indicators` добавить `x = 1 / 0`.
79 + * **Timerange:** Любой валидный.
80 + * **Ожидаемый результат:**
81 + 1. Агент **не падает**.
82 + 2. Инструмент возвращает `success: false` (или `true` с текстом ошибки, зависит от реализации парсера).
83 + 3. В поле `error` или `logTail` содержится Python Traceback: `ZeroDivisionError: division by zero`.
84 + 4. Пользователю выводится понятное сообщение: "Произошла ошибка в коде стратегии...".
85 +
86 + ### ✅ Тест-кейс 3.2: Отсутствующие рыночные данные (Invalid Pair)
87 + * **Описание:** Попытка запустить тест на несуществующей или делистинговой монете.
88 + * **Входные данные:**
89 + * **Config:** `pair_whitelist: ["SCAMTOKEN/USDT:USDT"]`.
90 + * **Timerange:** Любой.
91 + * **Ожидаемый результат:**
92 + 1. Бэктест **не начинается** (Docker не запускается).
93 + 2. Ошибка отлавливается на этапе `prepareMarketData`.
94 + 3. Сообщение об ошибке: `Missing slugs for pairs...` или `Data fetch failed`.
95 +
96 + ---
97 +
98 + ## 4. Чек-лист для ручного тестирования (Manual QA)
99 +
100 + Если автоматические тесты прошли, тестировщик должен проверить UX в диалоге с агентом:
101 +
102 + 1. [ ] Попросить агента: *"Протестируй стратегию за 2022 год"*. Агент должен сам сконвертировать это в формат `20220101-20221231`.
103 + 2. [ ] Попросить: *"Протестируй за последнюю неделю"*. Проверить, что даты корректны.
104 + 3. [ ] После успешного теста спросить: *"Какой был максимальный просад (drawdown)?"*. Агент должен прочитать это из логов (используя навык `backtest-reporter`).
105 +
106 + ---
107 +
108 + ## Пример кода для запуска Copy Trading теста (для разработчика)
109 +
110 + Этот код можно использовать в `scenarios.spec.ts` для Тест-кейса 2.1:
49 111
50 112 ```typescript
51 - it('Smoke Test: should complete a simple backtest successfully', async () => {
52 - // 1. Подготовка файлов (Strategy + Config)
53 - await writeFile(strategyPath, minimalWorkingStrategy);
54 - await writeFile(configPath, JSON.stringify(validConfig));
55 -
56 - // 2. Выполнение
57 - const result = await runBacktest.execute({ timerange: '20240101-20240105' }, context);
58 -
59 - // 3. Проверки
60 - expect(result.success).toBe(true);
61 - expect(result.logTail).toContain('Backtesting finished');
62 - expect(result.logTail).not.toContain('Traceback');
113 + it('Copy Trading: should open a trade when signal is present', async () => {
114 + // 1. Setup Strategy that mimics Copy Trading logic
115 + const copyStrategy = `
116 + class Strategy(IStrategy):
117 + def populate_indicators(self, dataframe, metadata):
118 + # MOCK SIGNAL: Force a buy signal on specific date
119 + dataframe['enter_long'] = 0
120 + dataframe.loc[dataframe['date'] == '2024-01-15 12:00:00+00:00', 'enter_long'] = 1
121 + return dataframe
122 + # ... rest of required methods
123 + `;
124 +
125 + // 2. Run Test around that date
126 + await setupArtifacts(copyStrategy, 'ETH/USDT:USDT');
127 + const result = await runBacktest.execute({ timerange: '20240114-20240116' });
128 +
129 + // 3. Assertions
130 + expect(result.success).toBe(true);
131 + // Проверяем, что сделка реально открылась
132 + expect(result.logTail).toMatch(/Total Trades\s+\|\s+1/);
133 + expect(result.logTail).toMatch(/Win Rate\s+\|\s+100%|0%/); // Сделка должна быть закрыта
63 134 });
64 135 ```

uxname's Avatar uxname revidoval tento gist 2 days ago. Přejít na revizi

1 file changed, 64 insertions

test ideas.md (vytvořil soubor)

@@ -0,0 +1,64 @@
1 + Отличный план. Вы правильно выделили два главных сценария (базовый и копитрейдинг). Чтобы покрытие было полным и гарантировало стабильность системы, я предлагаю дополнить их сценариями на обработку ошибок и граничные случаи.
2 +
3 + Вот **Топ-5 идей для тестов `backtest-runner`**, отсортированные от базовых к сложным:
4 +
5 + ### 1. "Smoke Test": Запуск примитивной стратегии (Infrastructure Check)
6 + **Суть:** Проверка всей цепочки без сложной логики. Стратегия должна быть максимально глупой (например, покупать на каждой четной свече и продавать на нечетной).
7 + * **Цель:** Убедиться, что Docker запускается, вольюмы монтируются, конфиг валиден, и Freqtrade в принципе способен завершить работу.
8 + * **Ожидаемый результат:**
9 + * Инструмент возвращает `success: true`.
10 + * В логах (`logTail`) присутствует фраза `Backtesting finished`.
11 + * В результатах есть хотя бы одна сделка.
12 +
13 + ### 2. "Data Fetcher Test": Копитрейдинг с реальными данными (SanR Integration)
14 + **Суть:** Тест стратегии, которая импортирует `sdk.py` и запрашивает сигналы для реального пользователя (например, `semaca`) и реальной пары (`BTC/USDT:USDT`).
15 + * **Цель:** Проверить работу `prepareMarketData`. Это самое узкое место. Тест должен убедиться, что:
16 + 1. Система парсит конфиг и находит нужные пары.
17 + 2. Делает запрос к SanR API / Santiment API.
18 + 3. Скачивает JSON-файлы в `market_cache`.
19 + 4. Freqtrade внутри Docker видит эти данные.
20 + * **Ожидаемый результат:** Бэктест проходит успешно, не падает с ошибкой `No data found`.
21 +
22 + ### 3. "The One-Day Edge Case": Граничный случай с датами
23 + **Суть:** Запуск бэктеста, где дата начала равна дате конца (например, `timerange: "20241001-20241001"`).
24 + * **Почему это важно:** В вашем коде (`src/mastra/pro/tools/freqtrade.ts` и `tools.ts`) есть специальная логика, которая расширяет такой диапазон на +1 день. Если это сломается, Freqtrade загрузит 0 свечей и выдаст ошибку.
25 + * **Ожидаемый результат:** Система должна автоматически расширить диапазон до `20241002`, загрузить данные за сутки и провести тест (24 свечи на 1h таймфрейме).
26 +
27 + ### 4. "The Crash Test": Обработка Runtime-ошибки в Python
28 + **Суть:** Подсунуть стратегию с синтаксически верным кодом, но с логической ошибкой, которая вызовет краш во время выполнения (например, деление на ноль в `populate_indicators` или обращение к несуществующей колонке DataFrame).
29 + * **Цель:** Проверить, как `backtest-runner` обрабатывает падение контейнера или Python-исключения. Агент не должен падать сам, он должен вернуть лог с ошибкой.
30 + * **Ожидаемый результат:**
31 + * Инструмент возвращает `success: false` (или `true`, но с явным описанием ошибки в логах).
32 + * В `logTail` содержится Python Traceback (например, `ZeroDivisionError`).
33 +
34 + ### 5. "Missing Data Handling": Запрос несуществующей пары
35 + **Суть:** В конфиге указать пару, которой не существует на бирже или в Santiment (например, `NONEXISTENTCOIN/USDT:USDT`).
36 + * **Цель:** Проверить валидацию данных до запуска тяжелого Docker-контейнера.
37 + * **Ожидаемый результат:**
38 + * Инструмент должен выбросить ошибку на этапе `prepareMarketData`.
39 + * Ошибка должна быть понятной: "Missing slugs for pairs..." или "Failed to fetch data".
40 + * Docker запускаться **не должен** (экономия ресурсов).
41 +
42 + ---
43 +
44 + ### Как это реализовать в коде (Пример для Vitest)
45 +
46 + Вы можете создать файл `src/mastra/super/skills/backtest-runner/scenarios.spec.ts` и реализовать эти сценарии, используя моки для `exec` (чтобы не ждать реальный докер долго) или реальные интеграционные тесты (как в примере 2).
47 +
48 + **Пример структуры теста для кейса №1:**
49 +
50 + ```typescript
51 + it('Smoke Test: should complete a simple backtest successfully', async () => {
52 + // 1. Подготовка файлов (Strategy + Config)
53 + await writeFile(strategyPath, minimalWorkingStrategy);
54 + await writeFile(configPath, JSON.stringify(validConfig));
55 +
56 + // 2. Выполнение
57 + const result = await runBacktest.execute({ timerange: '20240101-20240105' }, context);
58 +
59 + // 3. Проверки
60 + expect(result.success).toBe(true);
61 + expect(result.logTail).toContain('Backtesting finished');
62 + expect(result.logTail).not.toContain('Traceback');
63 + });
64 + ```
Novější Starší