refactor: remove legacy trading engine, streamline project to weather-only bot

This commit is contained in:
AmandaloveYang
2026-02-18 09:56:50 +08:00
parent d533bd5b21
commit 30f86eab89
29 changed files with 25 additions and 3644 deletions
View File
-95
View File
@@ -1,95 +0,0 @@
from loguru import logger
class OrderbookAnalyzer:
"""
分析目标: 评估市场供需平衡和流动性
"""
def __init__(self, config=None):
self.config = config or {}
self.wall_threshold = self.config.get("wall_threshold", 500) # 单笔订单超过此值为墙
logger.info("Initializing Orderbook Analyzer...")
def assess_liquidity(self, orderbook, side="ask"):
"""
分析流动性深度 (基于前 3 档)
"""
orders = orderbook.get('asks' if side == "ask" else 'bids', [])
if not orders:
return "枯竭", 0
# 前 3 档总量 (Polymarket 通常返回价格字符串)
depth = sum(float(o.get("size", 0)) for o in orders[:3])
if depth < 50:
return "稀薄", depth
elif depth < 500:
return "正常", depth
else:
return "充裕", depth
def analyze(self, orderbook):
"""
增强版订单簿分析:集成深度与 Spread 评估
"""
bids = orderbook.get('bids', [])
asks = orderbook.get('asks', [])
if not bids or not asks:
return {
"signal": "NEUTRAL",
"confidence": 0.0,
"tradeable": False,
"reason": "缺乏双边报价",
"liquidity": "枯竭",
"spread": 1.0
}
# 1. 计算核心指标
best_bid = float(bids[0].get('price', 0))
best_ask = float(asks[0].get('price', 0))
spread = abs(best_ask - best_bid)
mid_price = (best_ask + best_bid) / 2
# 2. 评估流动性
ask_liq, ask_depth = self.assess_liquidity(orderbook, "ask")
bid_liq, bid_depth = self.assess_liquidity(orderbook, "bid")
# 3. 交易可行性判定 (Spread <= 10c 且 深度 >= $50)
is_tradeable = (spread <= 0.10) and (ask_depth >= 50 or bid_depth >= 50)
# 4. Imbalance 计算
bid_volume = sum([float(b.get('size', 0)) for b in bids])
ask_volume = sum([float(a.get('size', 0)) for a in asks])
imbalance = bid_volume / ask_volume if ask_volume > 0 else 0
result = {
"best_bid": best_bid,
"best_ask": best_ask,
"mid_price": mid_price,
"spread": round(spread, 4),
"ask_depth": round(ask_depth, 2),
"bid_depth": round(bid_depth, 2),
"liquidity": ask_liq if ask_depth < bid_depth else bid_liq,
"tradeable": is_tradeable,
"imbalance": imbalance,
"signal": "NEUTRAL",
"confidence": 0.5
}
# 5. 信号修正
if is_tradeable:
if imbalance > 2.5:
result["signal"] = "BULLISH"
result["confidence"] = 0.75
elif imbalance < 0.4:
result["signal"] = "BEARISH"
result["confidence"] = 0.75
else:
result["confidence"] = 0.1 # 不建议交易
return result
def analyze_orderbook(orderbook):
"""兼容旧接口的便捷函数"""
analyzer = OrderbookAnalyzer()
return analyzer.analyze(orderbook)
-146
View File
@@ -1,146 +0,0 @@
import numpy as np
from loguru import logger
class TechnicalIndicators:
"""
技术指标计算 - RSI, 布林带等
"""
def __init__(self):
logger.info("Initializing Technical Indicators...")
def calculate_rsi(self, prices: list, period: int = 14) -> float:
"""
计算相对强弱指标 (RSI)
Args:
prices: 价格历史列表
period: RSI周期,默认14
Returns:
float: RSI值 (0-100)
"""
if len(prices) < period + 1:
logger.debug("Insufficient data for RSI calculation")
return 50.0 # 返回中性值
prices = np.array(prices)
deltas = np.diff(prices)
gains = np.where(deltas > 0, deltas, 0)
losses = np.where(deltas < 0, -deltas, 0)
avg_gain = np.mean(gains[-period:])
avg_loss = np.mean(losses[-period:])
if avg_loss == 0:
return 100.0
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
logger.debug(f"RSI({period}): {rsi:.2f}")
return rsi
def calculate_bollinger_bands(self, prices: list, period: int = 20, std_dev: float = 2.0) -> dict:
"""
计算布林带
Args:
prices: 价格历史列表
period: 移动平均周期
std_dev: 标准差倍数
Returns:
dict: 包含上轨、中轨、下轨
"""
if len(prices) < period:
logger.debug("Insufficient data for Bollinger Bands")
return {"upper": None, "middle": None, "lower": None}
prices = np.array(prices[-period:])
middle = np.mean(prices)
std = np.std(prices)
upper = middle + std_dev * std
lower = middle - std_dev * std
return {
"upper": upper,
"middle": middle,
"lower": lower,
"std": std
}
def calculate_momentum(self, prices: list, period: int = 10) -> float:
"""
计算价格动量
Args:
prices: 价格历史
period: 动量周期
Returns:
float: 动量值 (当前价格 / N周期前价格 - 1)
"""
if len(prices) < period + 1:
return 0.0
current = prices[-1]
past = prices[-period - 1]
if past == 0:
return 0.0
momentum = (current / past) - 1
return momentum
def get_signal(self, prices: list) -> dict:
"""
综合技术指标信号
Returns:
dict: 包含信号和分数
"""
rsi = self.calculate_rsi(prices)
bb = self.calculate_bollinger_bands(prices)
momentum = self.calculate_momentum(prices)
# RSI信号
if rsi > 70:
rsi_signal = "OVERBOUGHT"
rsi_score = 0.3 # 超买,看跌
elif rsi < 30:
rsi_signal = "OVERSOLD"
rsi_score = 0.8 # 超卖,看涨
else:
rsi_signal = "NEUTRAL"
rsi_score = 0.5
# 布林带信号
if bb["upper"] and len(prices) > 0:
current_price = prices[-1]
if current_price > bb["upper"]:
bb_signal = "ABOVE_UPPER"
bb_score = 0.7 # 突破上轨,强势
elif current_price < bb["lower"]:
bb_signal = "BELOW_LOWER"
bb_score = 0.3 # 跌破下轨,弱势
else:
bb_signal = "WITHIN_BANDS"
bb_score = 0.5
else:
bb_signal = "NO_DATA"
bb_score = 0.5
# 综合分数
combined_score = (rsi_score * 0.5 + bb_score * 0.3 +
(0.5 + momentum * 2) * 0.2) # momentum 转换为 0-1
combined_score = max(0, min(1, combined_score))
return {
"rsi": {"value": rsi, "signal": rsi_signal, "score": rsi_score},
"bollinger": {"bands": bb, "signal": bb_signal, "score": bb_score},
"momentum": momentum,
"combined_score": combined_score
}
-135
View File
@@ -1,135 +0,0 @@
import numpy as np
from loguru import logger
class VolumeAnalyzer:
"""
交易量异常检测 - 识别聪明钱和市场转折点
"""
def __init__(self, config=None):
self.config = config or {}
self.volume_threshold = self.config.get("volume_threshold", 2.0) # 2倍标准差
self.large_order_threshold = self.config.get("large_order_threshold", 1000) # $1000
logger.info("Initializing Volume Analyzer...")
def detect_volume_spike(self, volume_history: list) -> dict:
"""
检测成交量异常放大
Args:
volume_history: 历史成交量列表
Returns:
dict: 包含信号和置信度
"""
if len(volume_history) < 24:
return {"signal": "INSUFFICIENT_DATA", "score": 0.5}
recent_volume = np.array(volume_history[-24:]) # 最近24小时
historical_volume = np.array(volume_history[:-24])
if len(historical_volume) == 0:
return {"signal": "INSUFFICIENT_DATA", "score": 0.5}
avg_volume = np.mean(historical_volume)
std_volume = np.std(historical_volume)
recent_avg = np.mean(recent_volume)
# 计算Z-score
if std_volume > 0:
z_score = (recent_avg - avg_volume) / std_volume
else:
z_score = 0
logger.debug(f"Volume Z-score: {z_score:.2f}")
if z_score > self.volume_threshold:
return {
"signal": "VOLUME_SPIKE",
"score": min(0.9, 0.5 + z_score * 0.1),
"z_score": z_score,
"interpretation": "成交量异常放大,可能有新信息进入市场"
}
elif z_score < -self.volume_threshold:
return {
"signal": "VOLUME_DRY",
"score": 0.3,
"z_score": z_score,
"interpretation": "成交量萎缩,市场观望"
}
return {"signal": "NORMAL", "score": 0.5, "z_score": z_score}
def detect_large_orders(self, transactions: list) -> dict:
"""
检测大额订单 (聪明钱信号)
Args:
transactions: 交易列表,每个包含 size, side, price
Returns:
dict: 大额订单分析结果
"""
large_buys = []
large_sells = []
for tx in transactions:
size = tx.get("size", 0)
side = tx.get("side", "").upper()
if size >= self.large_order_threshold:
if side == "BUY":
large_buys.append(tx)
elif side == "SELL":
large_sells.append(tx)
total_large_buy = sum(t.get("size", 0) for t in large_buys)
total_large_sell = sum(t.get("size", 0) for t in large_sells)
logger.debug(f"Large buys: ${total_large_buy:.2f}, Large sells: ${total_large_sell:.2f}")
if total_large_buy > total_large_sell * 2:
return {
"signal": "SMART_MONEY_BUY",
"score": 0.8,
"large_buy_volume": total_large_buy,
"large_sell_volume": total_large_sell,
"interpretation": "大户在积极买入,跟随机会"
}
elif total_large_sell > total_large_buy * 2:
return {
"signal": "SMART_MONEY_SELL",
"score": 0.2,
"large_buy_volume": total_large_buy,
"large_sell_volume": total_large_sell,
"interpretation": "大户在抛售,风险警告"
}
return {
"signal": "NEUTRAL",
"score": 0.5,
"large_buy_volume": total_large_buy,
"large_sell_volume": total_large_sell
}
def analyze(self, volume_history: list, transactions: list = None) -> dict:
"""
综合分析交易量
"""
volume_signal = self.detect_volume_spike(volume_history)
if transactions:
order_signal = self.detect_large_orders(transactions)
else:
order_signal = {"signal": "NO_DATA", "score": 0.5}
# 综合评分
combined_score = (volume_signal.get("score", 0.5) * 0.6 +
order_signal.get("score", 0.5) * 0.4)
return {
"volume_signal": volume_signal,
"order_signal": order_signal,
"combined_score": combined_score
}
-59
View File
@@ -1,59 +0,0 @@
from loguru import logger
from typing import List, Dict
from src.data_collection.onchain_tracker import OnchainTracker
class WhaleTracker:
"""
大户行为分析模块
"""
def __init__(self, config: dict, tracker: OnchainTracker):
self.config = config
self.tracker = tracker
logger.info("Initializing Whale Tracker...")
def analyze_market_whales(self, market_id: str) -> Dict:
"""
分析特定市场的鲸鱼行为
"""
large_trades = self.tracker.get_large_transactions(market_id)
if not large_trades:
return {"bullish": False, "signal": "NEUTRAL", "reason": "No whale activity detected"}
buy_value = 0
sell_value = 0
for trade in large_trades:
side = trade.get("side", "").upper()
value = trade.get("value", 0)
if side == "BUY":
buy_value += value
else:
sell_value += value
# 判断情绪
if buy_value > sell_value * 2:
return {
"bullish": True,
"signal": "STRONG_ACCUMULATION",
"buy_value": buy_value,
"sell_value": sell_value,
"reason": "Whales are heavily buying"
}
elif sell_value > buy_value * 2:
return {
"bullish": False,
"signal": "STRONG_DISTRIBUTION",
"buy_value": buy_value,
"sell_value": sell_value,
"reason": "Whales are heavily selling"
}
return {
"bullish": buy_value > sell_value,
"signal": "MODERATE",
"buy_value": buy_value,
"sell_value": sell_value,
"reason": "Mixed whale activity"
}