优化信号

This commit is contained in:
2026-07-13 01:39:48 +08:00
parent cc79650769
commit a6fefa2c9c
10 changed files with 184 additions and 13 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ HTTP_PROXY=http://127.0.0.1:7890
# TAVILY_API_KEY= # 网页搜索 (https://tavily.com)
# TWITTER_API_KEY= # Twitter 社交情绪
# SERPER_API_KEY= # 网页搜索备用 (https://serper.dev)
# POLYGON_API_KEY= # 股票、外汇数据 (https://polygon.io)
# POLYGON_API_KEY= # 股票、外汇数据 (https://polygon.io, 已更名为 massive.com)
# FRED_API_KEY= # 美国经济指标 (https://fred.stlouisfed.org)
# ETHERSCAN_API_KEY= # 链上数据 (https://etherscan.io)
# CONGRESS_API_KEY= # 美国立法动态 (https://api.congress.gov)
+3
View File
@@ -0,0 +1,3 @@
{
"$schema": "https://app.kilo.ai/config.json"
}
+34
View File
@@ -0,0 +1,34 @@
import sqlite3
conn=sqlite3.connect('data/signals.db')
c=conn.cursor()
# Trade size vs IAS relationship
print("=== Trade Size vs IAS (by size bucket) ===")
for lo,hi in [(0,2000),(2000,5000),(5000,10000),(10000,20000),(20000,50000),(50000,999999)]:
row=c.execute('SELECT COUNT(*), AVG(information_asymmetry_score), AVG(trade_size_usd) FROM signals WHERE trade_size_usd>? AND trade_size_usd<=?',(lo,hi)).fetchone()
n=row[0]
if n>0:
avg_i = round(row[1],3)
avg_s = round(row[2],0)
print(f" ${lo:,.0f}-${hi:,.0f}: {n:3d} sigs, avg IAS={avg_i:.3f}, avg size=${avg_s:,.0f}")
print()
# Market question frequency
print("=== Top 10 Most Frequently Signaled Markets ===")
for r in c.execute('SELECT market_question, COUNT(*) as cnt, AVG(information_asymmetry_score) as avg_i FROM signals GROUP BY market_question ORDER BY cnt DESC LIMIT 10').fetchall():
print(f" {r[0][:65]:65s} | {r[1]:3d} sigs | avg IAS={r[2]:.3f}")
print()
# Resolution status
print("=== Unresolved Signals (PENDING) ===")
pending=c.execute('SELECT COUNT(*) FROM signals WHERE market_resolved IS NULL OR market_resolved=?',(0,)).fetchone()[0]
print(f" Pending: {pending}")
print()
# Trader wallet frequency
print("=== Top 10 Most Frequent Trader Wallets ===")
for r in c.execute('SELECT trader_wallet, COUNT(*) as cnt, AVG(information_asymmetry_score) as avg_i FROM signals GROUP BY trader_wallet ORDER BY cnt DESC LIMIT 10').fetchall():
print(f" {str(r[0])[:25]:25s} | {r[1]:3d} sigs | avg IAS={r[2]:.3f}")
+58
View File
@@ -0,0 +1,58 @@
import sqlite3, json
conn=sqlite3.connect('data/signals.db')
c=conn.cursor()
print("="*60)
print("SIGNALS DATABASE ANALYSIS")
print("="*60)
total=c.execute('SELECT COUNT(*) FROM signals').fetchone()[0]
resolved=c.execute('SELECT COUNT(*) FROM signals WHERE market_resolved=?',(1,)).fetchone()[0]
correct=c.execute('SELECT COUNT(*) FROM signals WHERE signal_correct=?',(1,)).fetchone()[0]
incorrect=c.execute('SELECT COUNT(*) FROM signals WHERE signal_correct=?',(0,)).fetchone()[0]
print(f"\nTotal signals: {total}")
print(f"Resolved: {resolved} | Correct: {correct} | Incorrect: {incorrect}")
print(f"Win rate: {correct/resolved:.2%}")
print(f"Avg ROI: {c.execute('SELECT AVG(theoretical_roi) FROM signals WHERE market_resolved=?',(1,)).fetchone()[0]:.2%}")
print("\n=== IAS Distribution ===")
for lo,hi in [(0.0,0.3),(0.3,0.4),(0.4,0.5),(0.5,0.6),(0.6,0.7),(0.7,0.8),(0.8,1.0)]:
row=c.execute('SELECT COUNT(*), AVG(information_asymmetry_score) FROM signals WHERE information_asymmetry_score>? AND information_asymmetry_score<=?',(lo,hi)).fetchone()
n=row[0]; avg=round(row[1],3) if row[1] else 0
bar='#'*int(n*0.4)
print(f" {lo}-{hi}: {n:3d} signals, avg={avg:.3f} {bar}")
print("\n=== Win Rate by IAS Tier ===")
for lo,hi in [(0.3,0.4),(0.4,0.5),(0.5,0.6),(0.6,0.7),(0.7,0.8),(0.8,1.0)]:
n=c.execute('SELECT COUNT(*) FROM signals WHERE information_asymmetry_score>? AND information_asymmetry_score<=?',(lo,hi)).fetchone()[0]
if n>0:
cr=c.execute('SELECT COUNT(*) FROM signals WHERE information_asymmetry_score>? AND information_asymmetry_score<=? AND signal_correct=?',(lo,hi,1)).fetchone()[0]
print(f" IAS {lo}-{hi}: {cr}/{n} correct ({cr/n:.1%})")
print("\n=== Trade Size Distribution ===")
bins=[(0,1000),(1000,2000),(2000,3000),(3000,5000),(5000,10000),(10000,20000),(20000,50000),(50000,999999)]
for lo,hi in bins:
row=c.execute('SELECT COUNT(*), AVG(trade_size_usd) FROM signals WHERE trade_size_usd>? AND trade_size_usd<=?',(lo,hi)).fetchone()
n=row[0]; avg=round(row[1],0) if row[1] else 0
if n>0:
print(f" ${lo:,.0f}-${hi:,.0f}: {n:3d} signals, avg ${avg:,.0f}")
print("\n=== Signal Time Range ===")
earliest=c.execute('SELECT MIN(detected_at) FROM signals').fetchone()[0]
latest=c.execute('SELECT MAX(detected_at) FROM signals').fetchone()[0]
print(f" First: {earliest}")
print(f" Last: {latest}")
print("\n=== Top 10 Signals by IAS ===")
for r in c.execute('SELECT trade_side, trade_outcome, trade_size_usd, trade_price, market_question, information_asymmetry_score, signal_correct, theoretical_roi FROM signals ORDER BY information_asymmetry_score DESC LIMIT 10').fetchall():
c_str='CORRECT' if r[6] else ('WRONG' if r[6] is not None else 'PENDING')
roi=f'{r[7]:.2%}' if r[7] else 'N/A'
print(f" IAS={r[5]:.2f} | {r[0]} {r[1]} @ {r[3]:.4f} ${r[2]:,.0f} | {r[4][:55]}... [{c_str}] ROI={roi}")
print("\n=== Sample LLM Analysis Reasoning (highest IAS) ===")
top=c.execute('SELECT reasoning, insider_evidence FROM signals ORDER BY information_asymmetry_score DESC LIMIT 3').fetchall()
for i, (reasoning, evidence) in enumerate(top):
print(f"\n--- Signal #{i+1} ---")
print(f"Reasoning (first 500 chars): {str(reasoning)[:500]}")
print(f"Insider evidence: {str(evidence)[:500] if evidence else 'None'}")
+78
View File
@@ -0,0 +1,78 @@
import json, collections, math
from datetime import datetime
with open('data/processed_transactions.json') as f:
txns = json.load(f)
print(f"Total transactions in file: {len(txns)}")
print()
# Sample
print("=== Sample (first 3) ===")
for t in txns[:3]:
print(json.dumps(t, indent=2))
print()
# Fields available
print("=== Available Fields ===")
sample = txns[0]
print(list(sample.keys()))
print()
# Direction distribution
print("=== Direction ===")
dirs = collections.Counter()
for t in txns:
dirs[t.get('side','?')]+=1
print(dirs)
print()
# Side breakdown
print("=== BUY vs SELL ===")
for s in ['BUY','SELL']:
n=sum(1 for t in txns if t.get('side')==s)
print(f" {s}: {n}")
print()
# Size distribution
print("=== Trade Size (USD) Distribution ===")
bins=[(0,100),(100,500),(500,1000),(1000,2000),(2000,5000),(5000,10000),(10000,20000),(20000,50000),(50000,100000),(100000,999999)]
for lo,hi in bins:
n=sum(1 for t in txns if lo<t.get('usdc_size',0)<=hi)
if n>0:
avg=sum(t.get('usdc_size',0) for t in txns if lo<t.get('usdc_size',0)<=hi)/n
print(f" ${lo:,.0f}-${hi:,.0f}: {n} txns, avg ${avg:,.0f}")
print()
# Price distribution
print("=== Price Distribution (BUY only) ===")
buy_txns=[t for t in txns if t.get('side')=='BUY']
price_bins=[(0,0.1),(0.1,0.2),(0.2,0.3),(0.3,0.4),(0.4,0.5),(0.5,0.6),(0.6,0.7),(0.7,0.8),(0.8,0.9),(0.9,1.0)]
for lo,hi in price_bins:
n=sum(1 for t in buy_txns if lo<=t.get('price',0)<hi)
if n>0:
print(f" {lo}-{hi}: {n}")
print()
# Largest trades
print("=== Top 20 Largest Trades (BUY) ===")
largest=sorted(buy_txns, key=lambda t: t.get('usdc_size',0), reverse=True)[:20]
for t in largest:
print(f" ${t['usdc_size']:,.0f} | {t['side']} {t.get('outcome','?')} @ {t['price']:.4f} | {t.get('title','?')[:60]}")
print()
# Check what happens at each filter stage
print("=== Filter Stage Analysis (BUY only, 0.0-0.95 price) ===")
print(f"BUY txns with price in 0.0-0.95: {sum(1 for t in buy_txns if 0<=t.get('price',0)<=0.95)}")
print(f"BUY txns size >= 1000: {sum(1 for t in buy_txns if t.get('usdc_size',0)>=1000)}")
print(f"BUY txns size >= 3000: {sum(1 for t in buy_txns if t.get('usdc_size',0)>=3000)}")
print(f"BUY txns size >= 5000: {sum(1 for t in buy_txns if t.get('usdc_size',0)>=5000)}")
print()
# Check if there are BUY txns >= 5000 with price in range
big_buy=[t for t in buy_txns if t.get('usdc_size',0)>=5000 and 0<=t.get('price',0)<=0.95]
print(f"BUY txns >= $5K and price in range: {len(big_buy)}")
if big_buy:
print(" Sample of qualifying transactions:")
for t in big_buy[:5]:
print(f" ${t['usdc_size']:,.0f} @ {t['price']:.4f} | vol={t.get('volume',0):,.0f}")
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -56,6 +56,7 @@ class Settings(BaseSettings):
min_trade_size_usd: float = Field(default=1000.0, alias="MIN_TRADE_SIZE_USD")
min_price: float = Field(default=0.10, alias="MIN_PRICE")
max_price: float = Field(default=0.90, alias="MAX_PRICE")
premium_threshold: float = Field(default=0.01, alias="PREMIUM_THRESHOLD")
# Monitoring Settings
trending_markets_limit: int = Field(default=50, alias="TRENDING_MARKETS_LIMIT")
+9 -12
View File
@@ -254,16 +254,16 @@ class TradeMonitor:
pass
# --- 4. Size ---
if activity.usdc_size < 3_000:
if activity.usdc_size < self.settings.min_trade_size_usd:
return False
# --- 5. Dynamic size ---
base_size = 5_000.0
base_size = max(self.settings.min_trade_size_usd, 5_000.0)
baseline_volume = 1_000_000.0
if market and market.volume > 0:
threshold = base_size * math.sqrt(market.volume / baseline_volume)
threshold = max(3_000.0, min(threshold, 50_000.0))
if market and market.volume_24hr > 0:
threshold = base_size * math.sqrt(market.volume_24hr / baseline_volume)
threshold = max(self.settings.min_trade_size_usd, min(threshold, 50_000.0))
else:
threshold = base_size
@@ -271,12 +271,9 @@ class TradeMonitor:
return False
# --- 5.5 Normalized size (like normalized_premium) ---
# usdc_size / √(volume) makes signals comparable across market sizes.
# A $5K trade in a $50K market is far more significant than $20K in a $10M market.
if market and market.volume > 0:
normalized = activity.usdc_size / math.sqrt(market.volume)
# Minimum normalized threshold: filters out trades that are trivial
# relative to market size (calibrated: $5K in a $1M market → 5.0)
# Use 24h volume so old markets don't suppress small trades.
if market and market.volume_24hr > 0:
normalized = activity.usdc_size / math.sqrt(market.volume_24hr)
if normalized < 1.5:
return False
@@ -289,7 +286,7 @@ class TradeMonitor:
else:
market_mid = 1.0 - market.outcome_prices[0]
if activity.price < market_mid + 0.01:
if activity.price < market_mid + self.settings.premium_threshold:
return False
return True