mirror of
https://github.com/triqbit/mt5-ai-xauusd-trader.git
synced 2026-11-02 06:56:15 +00:00
* docs: improve developer onboarding and contribution experience - Harden DX domain: format and fix 35+ files in scripts/ and migrations/. - Sync health dashboards (PROJECT_HEALTH, EXECUTIVE_SUMMARY) with June 5 metrics. - Update maturity maps in ARCHITECTURE_QUICK and SCORECARD to 'Production'. - Reduce total repo lint debt from 146 to 33. Co-authored-by: triqbit <242833443+triqbit@users.noreply.github.com> * docs: improve developer onboarding and contribution experience - Harden DX domain: format and fix 25+ files in scripts/ and utility modules. - Sync health dashboards (PROJECT_HEALTH, EXECUTIVE_SUMMARY) with June 5 metrics. - Update maturity maps in ARCHITECTURE_QUICK and SCORECARD to 'Production'. - Ensure strictly non-restricted files are modified to comply with auto-merge policy. Co-authored-by: triqbit <242833443+triqbit@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: triqbit <242833443+triqbit@users.noreply.github.com>
210 lines
6.5 KiB
Python
210 lines
6.5 KiB
Python
"""
|
|
MT5 AI/ML Trading Bot - Enterprise Edition
|
|
scripts/verify_journal_mining.py
|
|
Verification script for the journal mining system.
|
|
"""
|
|
|
|
import os
|
|
import random
|
|
import sys
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
# Ensure src is in path
|
|
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from src.analytics.journal_mining import JournalMiner
|
|
from src.core.trade_logger import Base, ModelSignal, RiskEvent, Trade
|
|
from src.research.reporting import ResearchOrchestrator, ResearchReporter
|
|
|
|
|
|
def generate_synthetic_data(db_url):
|
|
engine = create_engine(db_url)
|
|
Base.metadata.create_all(engine)
|
|
Session = sessionmaker(bind=engine)
|
|
|
|
with Session() as session:
|
|
# 1. Generate normal signals and trades
|
|
|
|
now = datetime.now(UTC)
|
|
|
|
# Profitable London session
|
|
for i in range(20):
|
|
# London session is 08-17 UTC
|
|
dt = now.replace(hour=10, minute=random.randint(0, 59)) - timedelta(
|
|
days=random.randint(1, 30)
|
|
)
|
|
sig = ModelSignal(
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0 + i,
|
|
algorithm="Ensemble_V2",
|
|
confidence=0.8,
|
|
volatility=0.1,
|
|
created_at=dt,
|
|
)
|
|
session.add(sig)
|
|
session.flush()
|
|
|
|
trd = Trade(
|
|
ticket=1000 + i,
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0 + i,
|
|
exit_price=2010.0 + i,
|
|
lot_size=0.1,
|
|
pnl=100.0,
|
|
status="CLOSED",
|
|
signal_id=sig.id,
|
|
created_at=dt,
|
|
updated_at=dt + timedelta(minutes=45),
|
|
)
|
|
session.add(trd)
|
|
|
|
# Toxic Combination: PPO + Dreamer before a drawdown
|
|
# Let's create 3 such clusters
|
|
for cluster_idx in range(3):
|
|
cluster_start = now - timedelta(days=cluster_idx + 2)
|
|
|
|
# Pre-cluster signals (Combination Motif)
|
|
sig1 = ModelSignal(
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0,
|
|
algorithm="PPO_Agent",
|
|
confidence=0.9,
|
|
volatility=0.5,
|
|
created_at=cluster_start - timedelta(minutes=30),
|
|
)
|
|
sig2 = ModelSignal(
|
|
symbol="XAUUSD",
|
|
direction=-1,
|
|
entry_price=2000.0,
|
|
algorithm="Dreamer_V3",
|
|
confidence=0.85,
|
|
volatility=0.5,
|
|
created_at=cluster_start - timedelta(minutes=25),
|
|
)
|
|
session.add_all([sig1, sig2])
|
|
session.flush()
|
|
|
|
# Drawdown cluster (3 losses)
|
|
for j in range(3):
|
|
dt = cluster_start + timedelta(minutes=j * 10)
|
|
sig = ModelSignal(
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0,
|
|
algorithm="PPO_Agent",
|
|
confidence=0.7,
|
|
volatility=0.5,
|
|
created_at=dt,
|
|
)
|
|
session.add(sig)
|
|
session.flush()
|
|
|
|
trd = Trade(
|
|
ticket=2000 + cluster_idx * 10 + j,
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0,
|
|
exit_price=1990.0,
|
|
lot_size=0.1,
|
|
pnl=-100.0,
|
|
status="CLOSED",
|
|
signal_id=sig.id,
|
|
created_at=dt,
|
|
updated_at=dt + timedelta(minutes=20),
|
|
)
|
|
session.add(trd)
|
|
|
|
# Risk event during weak state (during cluster)
|
|
evt = RiskEvent(
|
|
event_type="MAX_DRAWDOWN_BREACH",
|
|
description="Max drawdown reached during cluster",
|
|
symbol="XAUUSD",
|
|
created_at=cluster_start + timedelta(minutes=15),
|
|
)
|
|
session.add(evt)
|
|
|
|
# Overtrading in Sydney session (22-07 UTC)
|
|
for i in range(50):
|
|
dt = now.replace(hour=2, minute=random.randint(0, 59)) - timedelta(
|
|
days=random.randint(1, 10)
|
|
)
|
|
sig = ModelSignal(
|
|
symbol="XAUUSD",
|
|
direction=random.choice([1, -1]),
|
|
entry_price=2000.0,
|
|
algorithm="PPO_Agent",
|
|
confidence=0.5,
|
|
volatility=0.2,
|
|
created_at=dt,
|
|
)
|
|
session.add(sig)
|
|
session.flush()
|
|
|
|
# Mostly losses
|
|
pnl = random.choice([-50, -50, -50, 20])
|
|
trd = Trade(
|
|
ticket=3000 + i,
|
|
symbol="XAUUSD",
|
|
direction=1,
|
|
entry_price=2000.0,
|
|
exit_price=2000.0 + (pnl / 100),
|
|
lot_size=0.1,
|
|
pnl=pnl,
|
|
status="CLOSED",
|
|
signal_id=sig.id,
|
|
created_at=dt,
|
|
updated_at=dt + timedelta(minutes=120),
|
|
)
|
|
session.add(trd)
|
|
|
|
session.commit()
|
|
|
|
|
|
def main():
|
|
print("🚀 Starting Journal Mining Verification...")
|
|
db_url = "sqlite:///verify_journal.db"
|
|
|
|
# Cleanup old DB
|
|
if os.path.exists("verify_journal.db"):
|
|
os.remove("verify_journal.db")
|
|
|
|
# 1. Generate Data
|
|
print("📊 Generating synthetic trade data...")
|
|
generate_synthetic_data(db_url)
|
|
|
|
# 2. Run Mining
|
|
print("🔍 Running Journal Miner...")
|
|
miner = JournalMiner(db_url=db_url)
|
|
report_data = miner.run_mining()
|
|
|
|
# 3. Create Research Report
|
|
orchestrator = ResearchOrchestrator(
|
|
title="Institutional Trade Pattern Audit",
|
|
executive_summary="Automated mining of trade history to detect behavioral risks and signal motifs.",
|
|
conclusion="Journal mining complete. Several toxic patterns identified in Sydney session.",
|
|
overall_status="VERIFIED",
|
|
)
|
|
|
|
orchestrator.add_section(report_data.to_report_section())
|
|
|
|
# 4. Display Report
|
|
print("\n" + "=" * 50)
|
|
reporter = ResearchReporter()
|
|
reporter.format_for_terminal(orchestrator.build())
|
|
|
|
# Cleanup
|
|
if os.path.exists("verify_journal.db"):
|
|
os.remove("verify_journal.db")
|
|
|
|
print("✅ Verification complete!")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|