// ===========================
// File: src/config.rs
// ===========================
//
// Глобальная конфигурация Trading AI + загрузка ключей Gate.io
// из .env (GATE_API_KEY, GATE_SECRET_KEY).
//
use serde::Deserialize;
use std::env;
use dotenv::dotenv;
/// Глобальная конфигурация запуска Trading AI.
/// SCAN → поиск сверхволатильных пар
/// LIVE → торговля выбранной парой
#[derive(Clone, Debug, Deserialize)]
pub struct Config {
/// Redis URL
pub redis_url: String,
/// Идентификатор сессии
pub session_id: String,
/// Стартовый символ (не используется — LIVE берёт пару из SCAN)
pub symbol: String,
/// Резервный символ, если SCAN ничего не нашёл
pub fallback_symbol: String,
/// Пауза между LIVE-тиками (мс)
pub tick_delay_ms: u64,
/// Горизонт прогнозирования (для других модулей)
pub horizon_steps: usize,
pub horizon_step_pct: f64,
// ----------------------------------------------------
// Фильтрация волатильности для SCAN-движка
// ----------------------------------------------------
/// Минимальная волатильность (% за 24ч)
pub min_volatility_pct: f64,
/// Максимальная волатильность (% за 24ч)
pub max_volatility_pct: f64,
/// Сколько пар проверяет SCAN за тик
pub scan_pairs_count: usize,
/// Баланс USDT для расчёта размера позиции
pub balance_usdt: f64,
}
impl Config {
pub fn load() -> Self {
// Подтянем переменные окружения из .env, если он есть
let _ = dotenv();
Self {
redis_url: env::var("REDIS_URL")
.unwrap_or_else(|_| "redis://127.0.0.1/".to_string()),
session_id: env::var("SESSION_ID")
.unwrap_or_else(|_| "volatility-trader-1".to_string()),
// Стартовые значения — не используются напрямую, но нужны для init
symbol: env::var("START_SYMBOL")
.unwrap_or_else(|_| "VOLATILE_PAIRS".to_string()),
fallback_symbol: env::var("FALLBACK_SYMBOL")
.unwrap_or_else(|_| "".to_string()),
// LIVE режим: быстрые тики (ваш стандарт)
tick_delay_ms: env::var("TICK_DELAY_MS")
.ok()
.and_then(|v| v.parse::<u64>().ok())
.unwrap_or(100),
// Горизонт анализа (для внешних модулей)
horizon_steps: env::var("HORIZON_STEPS")
.ok()
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(20),
horizon_step_pct: env::var("HORIZON_STEP_PCT")
.ok()
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(2.0),
// SCAN фильтрует сверх-волатильные пары (минимум 15% за 24ч)
min_volatility_pct: env::var("MIN_VOL_PCT")
.ok()
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(15.0),
max_volatility_pct: env::var("MAX_VOL_PCT")
.ok()
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(1000.0),
// Проверяем N пар из списка лидеров
scan_pairs_count: env::var("SCAN_PAIRS_COUNT")
.ok()
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(50),
// Баланс USDT для расчёта размера позиции (3% от депо)
balance_usdt: env::var("BALANCE_USDT")
.ok()
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(50.0),
}
}
}
/// Ключи API для Gate.io, берём из .env:
/// GATE_API_KEY
/// GATE_SECRET_KEY
#[derive(Clone, Debug)]
pub struct ApiKeys {
pub gate_api_key: String,
pub gate_secret_key: String,
}
impl ApiKeys {
pub fn load() -> Self {
// .env уже мог быть прочитан выше, но если нет — ничего страшного.
let _ = dotenv();
let gate_api_key = env::var("GATE_API_KEY")
.expect("GATE_API_KEY не найден в окружении (.env)");
let gate_secret_key = env::var("GATE_SECRET_KEY")
.expect("GATE_SECRET_KEY не найден в окружении (.env)");
Self {
gate_api_key,
gate_secret_key,
}
}
}