210 lines
9.6 KiB
Python
210 lines
9.6 KiB
Python
"""
|
||
配置管理模块
|
||
从环境变量加载配置
|
||
"""
|
||
import os
|
||
from pathlib import Path
|
||
from typing import Optional
|
||
from pydantic_settings import BaseSettings
|
||
from functools import lru_cache
|
||
|
||
|
||
# 查找.env文件的位置
|
||
def find_env_file():
|
||
"""查找.env文件,支持从backend目录或项目根目录启动"""
|
||
current_dir = Path.cwd()
|
||
|
||
# 尝试当前目录
|
||
env_path = current_dir / ".env"
|
||
if env_path.exists():
|
||
print(f"[Config] 找到.env文件: {env_path}")
|
||
return str(env_path)
|
||
|
||
# 尝试父目录(项目根目录)
|
||
env_path = current_dir.parent / ".env"
|
||
if env_path.exists():
|
||
print(f"[Config] 找到.env文件: {env_path}")
|
||
return str(env_path)
|
||
|
||
# 尝试backend的父目录
|
||
if current_dir.name == "backend":
|
||
env_path = current_dir.parent / ".env"
|
||
if env_path.exists():
|
||
print(f"[Config] 找到.env文件: {env_path}")
|
||
return str(env_path)
|
||
|
||
# 尝试从环境变量指定的路径
|
||
if os.getenv('ENV_FILE'):
|
||
env_path = Path(os.getenv('ENV_FILE'))
|
||
if env_path.exists():
|
||
print(f"[Config] 从ENV_FILE环境变量找到.env文件: {env_path}")
|
||
return str(env_path)
|
||
|
||
print(f"[Config] 警告:未找到.env文件,当前目录: {current_dir}")
|
||
# 默认返回当前目录的.env
|
||
return ".env"
|
||
|
||
|
||
class Settings(BaseSettings):
|
||
"""应用配置"""
|
||
|
||
# Tushare配置
|
||
tushare_token: str = ""
|
||
|
||
# LLM配置
|
||
zhipuai_api_key: str = ""
|
||
deepseek_api_key: str = ""
|
||
|
||
# 数据库配置
|
||
database_url: str = "sqlite:///./stock_agent.db"
|
||
|
||
# API配置
|
||
api_host: str = "0.0.0.0"
|
||
api_port: int = 8000
|
||
debug: bool = True
|
||
|
||
# 安全配置
|
||
secret_key: str = "change-this-secret-key-in-production"
|
||
rate_limit: str = "100/minute"
|
||
|
||
# JWT配置
|
||
jwt_algorithm: str = "HS256"
|
||
jwt_expire_days: int = 7
|
||
|
||
# 腾讯云短信配置
|
||
tencent_sms_app_id: str = "1400961527"
|
||
tencent_sms_secret_id: str = "AKIDxnbGj281iHtKallqqzvlV5YxBCrPltnS" # 腾讯云SecretId
|
||
tencent_sms_secret_key: str = "ta6PXTMBsX7dzA7IN6uYUFn8F9uTovoU" # 腾讯云SecretKey
|
||
tencent_sms_sign_id: str = "629073"
|
||
tencent_sms_template_id: str = "2353142"
|
||
|
||
# 验证码配置
|
||
code_expire_minutes: int = 5
|
||
code_resend_seconds: int = 60
|
||
code_max_per_hour: int = 10
|
||
|
||
# 白名单手机号(无需验证码即可登录)
|
||
whitelist_phones: str = "18583366860,18583926860"
|
||
|
||
# CORS配置
|
||
cors_origins: str = "http://localhost:8000,http://127.0.0.1:8000"
|
||
|
||
# Binance 配置(公开数据不需要 API 密钥)
|
||
binance_api_key: str = ""
|
||
binance_api_secret: str = ""
|
||
|
||
# 飞书机器人配置
|
||
feishu_crypto_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/8a1dcf69-6753-41e2-a393-edc4f7822db0" # 加密货币通知
|
||
feishu_stock_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/408ab727-0dcd-4c7a-bde7-4aad38cbf807" # 股票通知
|
||
feishu_news_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/c7fd0db7-d295-451c-b943-130278a6cd9d" # 新闻智能体通知
|
||
feishu_error_webhook_url: str = "https://open.feishu.cn/open-apis/bot/v2/hook/ba6952c9-3b0c-4bc1-8a43-ceaacb27b043" # 系统异常通知
|
||
feishu_enabled: bool = True # 是否启用飞书通知
|
||
|
||
# Telegram 机器人配置
|
||
telegram_bot_token: str = "" # 从 @BotFather 获取
|
||
telegram_channel_id: str = "" # 频道 ID,如 @your_channel 或 -1001234567890
|
||
telegram_enabled: bool = True # 是否启用 Telegram 通知
|
||
|
||
# 钉钉机器人配置
|
||
dingtalk_webhook_url: str = "https://oapi.dingtalk.com/robot/send?access_token=a4fa1c1a6a07a5ed07d79c701f79b44efb1e726da3b47b50495ebdc9190423ec" # 钉钉群机器人 Webhook
|
||
dingtalk_secret: str = "SECdc6dffe3b6838a5d8afde3486d5415b9a17d3ebc9cbf934438883acee1189e8d" # 加签密钥
|
||
dingtalk_enabled: bool = True # 是否启用钉钉通知
|
||
|
||
# 加密货币交易智能体配置
|
||
crypto_symbols: str = "BTCUSDT,ETHUSDT" # 监控的交易对,逗号分隔
|
||
crypto_analysis_interval: int = 60 # 分析间隔(秒)
|
||
crypto_llm_threshold: float = 0.70 # 触发 LLM 分析的置信度阈值
|
||
|
||
# 价格监控模式配置
|
||
use_bitget_websocket: bool = True # 是否使用 Bitget WebSocket 实时价格(默认 False 使用 Binance 轮询)
|
||
|
||
# 波动率过滤配置(节省 LLM 调用)
|
||
crypto_volatility_filter_enabled: bool = True # 是否启用波动率过滤
|
||
crypto_min_volatility_percent: float = 0.5 # 最小波动率(百分比),低于此值跳过分析
|
||
crypto_min_price_range_percent: float = 0.3 # 最小价格变动范围(百分比),低于此值跳过分析
|
||
crypto_5m_surge_threshold: float = 1.0 # 5分钟突发波动阈值(百分比),超过此值即使1小时波动率低也会触发分析
|
||
|
||
# Brave Search API 配置
|
||
brave_api_key: str = ""
|
||
|
||
# 模拟交易配置
|
||
paper_trading_enabled: bool = True # 是否启用模拟交易
|
||
paper_trading_initial_balance: float = 10000 # 初始本金 (USDT)
|
||
paper_trading_leverage: int = 20 # 杠杆倍数(全仓模式下的最大杠杆)
|
||
paper_trading_margin_per_order: float = 1000 # 每单保证金 (USDT)
|
||
paper_trading_max_orders: int = 10 # 最大持仓+挂单总数
|
||
paper_trading_auto_close_opposite: bool = False # 是否自动平掉反向持仓(智能策略)
|
||
paper_trading_breakeven_threshold: float = 1 # 保本止损触发阈值(盈利百分比),0表示禁用
|
||
|
||
# 移动止损配置
|
||
paper_trading_trailing_stop_enabled: bool = True # 是否启用移动止损
|
||
paper_trading_trailing_stop_threshold_multiplier: float = 2 # 移动止损触发倍数(相对于保本阈值)
|
||
paper_trading_trailing_stop_ratio: float = 0.5 # 移动止损跟随比例(0-1之间,1表示完全跟随)
|
||
|
||
# 动态止盈配置(趋势过滤)
|
||
paper_trading_dynamic_tp_enabled: bool = True # 是否启用动态止盈
|
||
paper_trading_strong_trend_ratio: float = 0.7 # 强趋势时移动止损跟随比例(70%)
|
||
paper_trading_weak_trend_ratio: float = 0.3 # 弱趋势时移动止损跟随比例(30%)
|
||
paper_trading_sideways_tp_percent: float = 3 # 震荡市固定止盈百分比(3%)
|
||
# 废弃的配置(保留兼容性)
|
||
paper_trading_position_a: float = 1000 # A级信号仓位 (USDT)
|
||
paper_trading_position_b: float = 500 # B级信号仓位 (USDT)
|
||
paper_trading_position_c: float = 200 # C级信号仓位 (USDT)
|
||
|
||
# ========== 实盘交易配置 ==========
|
||
# Bitget API 配置
|
||
bitget_api_key: str = "" # Bitget API Key
|
||
bitget_api_secret: str = "" # Bitget API Secret
|
||
bitget_passphrase: str = "" # Bitget API Passphrase
|
||
bitget_use_testnet: bool = True # 是否使用测试网(测试时设为 true)
|
||
|
||
# 实盘交易开关
|
||
real_trading_enabled: bool = False # 实盘交易总开关(false 时仅模拟交易生效)
|
||
|
||
# 实盘交易风险控制
|
||
real_trading_max_single_position: float = 1000 # 单笔最大持仓金额 (USDT)
|
||
real_trading_max_total_ratio: float = 0.5 # 最大总仓位比例(账户的50%)
|
||
real_trading_default_leverage: int = 10 # 实盘默认杠杆(低于模拟)
|
||
real_trading_risk_per_trade: float = 0.02 # 每笔交易风险比例(2%)
|
||
real_trading_max_orders: int = 5 # 实盘最大同时持仓数
|
||
|
||
# Agent 模型配置 (可选值: zhipu, deepseek)
|
||
smart_agent_model: str = "deepseek" # SmartAgent 使用的模型
|
||
crypto_agent_model: str = "deepseek" # CryptoAgent 使用的模型
|
||
stock_agent_model: str = "deepseek" # StockAgent 使用的模型
|
||
|
||
# 股票智能体配置
|
||
stock_symbols_us: str = "" # 美股代码,逗号分隔
|
||
# 港股代码:科技+新能源+芯片+AI+金融+汽车+医药+消费+能源(统一格式:去掉前导零)
|
||
# 科技:腾讯控股/阿里巴巴/美团/小米集团/京东集团/网易/百度/快手/知乎/B站
|
||
# 新能源:比亚迪/理想汽车/小鹏汽车/赣锋锂业/龙源电力/信义能源
|
||
# 芯片:中芯国际/华虹半导体/上海复旦
|
||
# AI:商汤/第四范式/创新奇智/美图/联易融/百融云
|
||
# 金融:汇控/建行/工行/农行/中行/友邦/平安/国寿/中金/中信
|
||
# 汽车:蔚来/长城汽车/吉利汽车
|
||
# 医药:药明康德/药明生物/百济神州/信达生物/石药集团
|
||
# 消费:名创优品/泡泡玛特/安踏体育
|
||
# 能源:中海油/中石油/中国神华
|
||
stock_symbols_hk: str = "700.HK,9988.HK,3690.HK,1810.HK,9618.HK,9999.HK,9888.HK,1024.HK,2390.HK,9626.HK,1211.HK,2015.HK,9868.HK,1772.HK,916.HK,3868.HK,981.HK,1347.HK,1385.HK,20.HK,6682.HK,2121.HK,1357.HK,9959.HK,6608.HK,5.HK,939.HK,1398.HK,1288.HK,3988.HK,1299.HK,2318.HK,2628.HK,3908.HK,6030.HK,9866.HK,2333.HK,175.HK,2359.HK,2269.HK,6160.HK,1801.HK,1093.HK,9896.HK,9992.HK,2020.HK,883.HK,857.HK,1088.HK"
|
||
stock_analysis_interval: int = 300 # 分析间隔(秒,默认5分钟)
|
||
stock_llm_threshold: float = 0.70 # 触发 LLM 分析的置信度阈值
|
||
|
||
# A股智能体配置
|
||
astock_monitor_enabled: bool = True # 是否启用A股智能体
|
||
astock_change_threshold: float = 2.0 # 涨跌幅阈值(%),超过此值触发异动
|
||
astock_top_n: int = 3 # 每个板块返回前N只龙头股
|
||
astock_check_interval: int = 30 # 检查间隔(分钟)
|
||
# 钉钉通知配置(A股专用)
|
||
dingtalk_astock_webhook: str = "" # A股钉钉通知 Webhook
|
||
dingtalk_astock_secret: str = "" # A股钉钉通知加签密钥
|
||
|
||
class Config:
|
||
env_file = find_env_file()
|
||
case_sensitive = False
|
||
|
||
|
||
@lru_cache()
|
||
def get_settings() -> Settings:
|
||
"""获取配置单例"""
|
||
return Settings()
|