59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
import json
|
|
import logging
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from .fetcher import BinanceFetcher
|
|
from .filters import StrategyFilters
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class UniverseEngine:
|
|
def __init__(self, config: dict):
|
|
self.config = config
|
|
self.fetcher = BinanceFetcher(config)
|
|
self.filters = StrategyFilters(config)
|
|
|
|
async def run_pipeline(self):
|
|
try:
|
|
# 1. 基础池
|
|
liquid_symbols = await self.fetcher.get_liquid_symbols()
|
|
if not liquid_symbols:
|
|
logger.error("基础池为空,请检查网络/代理或放宽 base_filter 阈值。")
|
|
return {}
|
|
|
|
# 2. 获取数据
|
|
data_dict = await self.fetcher.fetch_klines_batch(liquid_symbols)
|
|
if not data_dict:
|
|
logger.error("K 线拉取全部失败,请检查网络或降低并发。")
|
|
return {}
|
|
|
|
# 3. 执行策略过滤
|
|
results = {
|
|
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
'timeframe': self.config['data']['timeframe'],
|
|
'quote_currencies': self.fetcher.quote_currencies,
|
|
'trend_universe': self.filters.filter_trend(data_dict),
|
|
'mr_universe': self.filters.filter_mean_reversion(data_dict),
|
|
'starb_pairs': self.filters.filter_starb(data_dict),
|
|
}
|
|
|
|
# 4. 保存结果
|
|
self._save_results(results)
|
|
return results
|
|
finally:
|
|
await self.fetcher.close()
|
|
|
|
def _save_results(self, results: dict):
|
|
save_path = Path(
|
|
self.config.get('output', {}).get('save_path', './output/universe_results.json')
|
|
)
|
|
save_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
# tuple 转 list 方便 JSON 序列化
|
|
results['starb_pairs'] = [list(p) for p in results['starb_pairs']]
|
|
|
|
with open(save_path, 'w', encoding='utf-8') as f:
|
|
json.dump(results, f, indent=4, ensure_ascii=False)
|
|
logger.info(f"标的池结果已保存至: {save_path}") |