125 lines
3.9 KiB
Python
125 lines
3.9 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""
|
||
|
|
DOLPHIN Paper Trading Monitor
|
||
|
|
==============================
|
||
|
|
Simple status display for the paper trading system.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import json
|
||
|
|
import time
|
||
|
|
from pathlib import Path
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
sys.path.insert(0, '/mnt/dolphinng5_predict')
|
||
|
|
sys.path.insert(0, '/mnt/dolphinng5_predict/nautilus_dolphin')
|
||
|
|
import hazelcast
|
||
|
|
|
||
|
|
|
||
|
|
def get_latest_arrow_info():
|
||
|
|
"""Get latest scan info directly from Arrow files."""
|
||
|
|
arrow_dir = Path('/mnt/ng6_data/arrow_scans') / datetime.now().strftime('%Y-%m-%d')
|
||
|
|
|
||
|
|
latest_file = None
|
||
|
|
latest_mtime = 0
|
||
|
|
|
||
|
|
try:
|
||
|
|
with os.scandir(arrow_dir) as it:
|
||
|
|
for entry in it:
|
||
|
|
if entry.name.endswith('.arrow') and entry.is_file():
|
||
|
|
mtime = entry.stat().st_mtime
|
||
|
|
if mtime > latest_mtime:
|
||
|
|
latest_mtime = mtime
|
||
|
|
latest_file = entry.path
|
||
|
|
except FileNotFoundError:
|
||
|
|
return None
|
||
|
|
|
||
|
|
if not latest_file:
|
||
|
|
return None
|
||
|
|
|
||
|
|
# Read scan info
|
||
|
|
import pyarrow as pa
|
||
|
|
import pyarrow.ipc as ipc
|
||
|
|
|
||
|
|
with pa.memory_map(latest_file, 'r') as source:
|
||
|
|
table = ipc.open_file(source).read_all()
|
||
|
|
|
||
|
|
return {
|
||
|
|
'scan_number': table.column('scan_number')[0].as_py(),
|
||
|
|
'timestamp_iso': table.column('timestamp_iso')[0].as_py(),
|
||
|
|
'assets': len(json.loads(table.column('assets_json')[0].as_py())),
|
||
|
|
'instability': table.column('instability_composite')[0].as_py(),
|
||
|
|
'age_sec': time.time() - latest_mtime,
|
||
|
|
'file': os.path.basename(latest_file)
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def get_hz_info(client):
|
||
|
|
"""Get Hazelcast scan info."""
|
||
|
|
features_map = client.get_map('DOLPHIN_FEATURES').blocking()
|
||
|
|
val = features_map.get('latest_eigen_scan')
|
||
|
|
|
||
|
|
if not val:
|
||
|
|
return None
|
||
|
|
|
||
|
|
data = json.loads(val)
|
||
|
|
mtime = data.get('file_mtime', 0)
|
||
|
|
|
||
|
|
return {
|
||
|
|
'scan_number': data.get('scan_number'),
|
||
|
|
'assets': len(data.get('assets', [])),
|
||
|
|
'prices': len(data.get('prices', [])),
|
||
|
|
'instability': data.get('instability_composite'),
|
||
|
|
'age_sec': time.time() - mtime if mtime else None,
|
||
|
|
'bridge_ts': data.get('bridge_ts', 'N/A')[:19] if data.get('bridge_ts') else 'N/A'
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
print("=" * 70)
|
||
|
|
print("🐬 DOLPHIN PAPER TRADING MONITOR")
|
||
|
|
print("=" * 70)
|
||
|
|
|
||
|
|
# Arrow file status
|
||
|
|
arrow_info = get_latest_arrow_info()
|
||
|
|
if arrow_info:
|
||
|
|
print(f"\n📁 ARROW FILES:")
|
||
|
|
print(f" Latest: #{arrow_info['scan_number']} ({arrow_info['file']})")
|
||
|
|
print(f" Assets: {arrow_info['assets']} | Instability: {arrow_info['instability']:.4f}")
|
||
|
|
print(f" Age: {arrow_info['age_sec']:.1f}s")
|
||
|
|
else:
|
||
|
|
print("\n📁 ARROW FILES: Not found")
|
||
|
|
|
||
|
|
# Hazelcast status
|
||
|
|
try:
|
||
|
|
client = hazelcast.HazelcastClient(
|
||
|
|
cluster_name="dolphin",
|
||
|
|
cluster_members=["localhost:5701"],
|
||
|
|
)
|
||
|
|
|
||
|
|
hz_info = get_hz_info(client)
|
||
|
|
if hz_info:
|
||
|
|
print(f"\n⚡ HAZELCAST (DOLPHIN_FEATURES):")
|
||
|
|
print(f" Scan: #{hz_info['scan_number']} | Assets: {hz_info['assets']} | Prices: {hz_info['prices']}")
|
||
|
|
print(f" Instability: {hz_info['instability']:.4f}")
|
||
|
|
print(f" File Age: {hz_info['age_sec']:.1f}s | Bridged: {hz_info['bridge_ts']}")
|
||
|
|
|
||
|
|
# Check if bridge is current
|
||
|
|
if arrow_info and hz_info['scan_number'] == arrow_info['scan_number']:
|
||
|
|
print(f" ✓ Bridge SYNCED")
|
||
|
|
else:
|
||
|
|
print(f" ⚠ Bridge LAGGING (Arrow: #{arrow_info['scan_number']}, Hz: #{hz_info['scan_number']})")
|
||
|
|
else:
|
||
|
|
print(f"\n⚡ HAZELCAST: No latest_eigen_scan found!")
|
||
|
|
|
||
|
|
client.shutdown()
|
||
|
|
except Exception as e:
|
||
|
|
print(f"\n⚡ HAZELCAST: Connection failed - {e}")
|
||
|
|
|
||
|
|
print("\n" + "=" * 70)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|