refactor: restructure repository and add README, CLAUDE.md, LICENSE

- Move utility scripts to scripts/ (check_market, check_positions, etc.)
- Move test files to tests/ (test_modules, test_mt5_connection, etc.)
- Move deprecated dashboards to archive/
- Move research files to docs/research/
- Add sys.path fix to all moved Python files
- Rewrite README.md with architecture diagram and badges
- Add CLAUDE.md project guide
- Add MIT LICENSE
- Update .gitignore with archive/ pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
GifariKemal
2026-02-06 13:22:46 +07:00
parent 20dc1385c3
commit 0d25548ed5
25 changed files with 364 additions and 82 deletions
+114
View File
@@ -0,0 +1,114 @@
"""Quick market analysis script"""
# Run from project root: python scripts/check_market.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from dotenv import load_dotenv
load_dotenv()
from src.mt5_connector import MT5Connector
from src.smc_polars import SMCAnalyzer
from src.config import TradingConfig
config = TradingConfig()
mt5 = MT5Connector(config.mt5_login, config.mt5_password, config.mt5_server, config.mt5_path)
mt5.connect()
# Get data
df = mt5.get_market_data('XAUUSD', 'M15', 500)
print('=== MARKET DATA ===')
print(f'Candles: {len(df)}')
print(f'Last close: {df["close"].tail(1).item():.2f}')
# Current price
tick = mt5.get_tick('XAUUSD')
print(f'Bid: {tick.bid:.2f}, Ask: {tick.ask:.2f}')
print(f'Spread: {(tick.ask - tick.bid):.2f}')
# SMC Analysis
smc = SMCAnalyzer()
df_smc = smc.calculate_all(df)
# Check last 20 candles for SMC patterns
print('')
print('=== SMC PATTERNS (Last 20 candles) ===')
last_20 = df_smc.tail(20).select(['time', 'close', 'bos', 'choch', 'is_fvg_bull', 'is_fvg_bear', 'ob', 'fvg_signal', 'market_structure']).to_dicts()
pattern_found = False
for i, row in enumerate(last_20):
markers = []
if row.get('bos', 0) != 0:
markers.append(f'BOS={row["bos"]}')
if row.get('choch', 0) != 0:
markers.append(f'CHoCH={row["choch"]}')
if row.get('is_fvg_bull'):
markers.append('FVG_BULL')
if row.get('is_fvg_bear'):
markers.append('FVG_BEAR')
if row.get('ob', 0) > 0:
markers.append('OB_BULL')
if row.get('ob', 0) < 0:
markers.append('OB_BEAR')
if markers:
pattern_found = True
print(f' [{i}] {row["close"]:.2f} | {" | ".join(markers)}')
if not pattern_found:
print(' No patterns in last 20 candles!')
# Generate signal
signal = smc.generate_signal(df_smc)
print('')
print('=== SMC SIGNAL RESULT ===')
if signal:
print(f'Signal: {signal.signal_type}')
print(f'Entry: {signal.entry_price:.2f}')
print(f'SL: {signal.stop_loss:.2f}')
print(f'TP: {signal.take_profit:.2f}')
print(f'Confidence: {signal.confidence:.0%}')
print(f'Reason: {signal.reason}')
else:
print('Signal: NONE - No valid setup')
# Check last 5 candles
print('')
print('Last 5 candles detail:')
last_5 = df_smc.tail(5).to_dicts()
for i, row in enumerate(last_5):
print(f' [{i}] Close={row["close"]:.2f}, BOS={row.get("bos",0)}, CHoCH={row.get("choch",0)}, FVG_B={row.get("is_fvg_bull",False)}, FVG_S={row.get("is_fvg_bear",False)}, OB={row.get("ob",0)}')
# Check overall SMC stats
print('')
print('=== SMC STATISTICS (All 500 candles) ===')
bos_bull = df_smc.filter(df_smc['bos'] > 0).height
bos_bear = df_smc.filter(df_smc['bos'] < 0).height
choch_bull = df_smc.filter(df_smc['choch'] > 0).height
choch_bear = df_smc.filter(df_smc['choch'] < 0).height
fvg_bull = df_smc.filter(df_smc['is_fvg_bull'] == True).height
fvg_bear = df_smc.filter(df_smc['is_fvg_bear'] == True).height
ob_bull = df_smc.filter(df_smc['ob'] > 0).height
ob_bear = df_smc.filter(df_smc['ob'] < 0).height
print(f'BOS Bullish: {bos_bull}, BOS Bearish: {bos_bear}')
print(f'CHoCH Bullish: {choch_bull}, CHoCH Bearish: {choch_bear}')
print(f'FVG Bullish: {fvg_bull}, FVG Bearish: {fvg_bear}')
print(f'OB Bullish: {ob_bull}, OB Bearish: {ob_bear}')
# Check when was the last BOS/CHoCH
print('')
print('=== LAST STRUCTURE BREAKS ===')
bos_indices = df_smc.with_row_index().filter(df_smc['bos'] != 0).select(['index', 'time', 'close', 'bos']).tail(3).to_dicts()
choch_indices = df_smc.with_row_index().filter(df_smc['choch'] != 0).select(['index', 'time', 'close', 'choch']).tail(3).to_dicts()
print('Last 3 BOS:')
for row in bos_indices:
candles_ago = 499 - row['index']
print(f' {row["time"]} | Close={row["close"]:.2f} | BOS={row["bos"]} | {candles_ago} candles ago')
print('Last 3 CHoCH:')
for row in choch_indices:
candles_ago = 499 - row['index']
print(f' {row["time"]} | Close={row["close"]:.2f} | CHoCH={row["choch"]} | {candles_ago} candles ago')
mt5.disconnect()
+59
View File
@@ -0,0 +1,59 @@
"""Check open positions and account status."""
# Run from project root: python scripts/check_positions.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from dotenv import load_dotenv
load_dotenv()
import MetaTrader5 as mt5
# Connect
mt5.initialize(
login=int(os.getenv("MT5_LOGIN")),
password=os.getenv("MT5_PASSWORD"),
server=os.getenv("MT5_SERVER"),
path=os.getenv("MT5_PATH"),
)
# Account info
account = mt5.account_info()
print("=" * 50)
print("ACCOUNT STATUS")
print("=" * 50)
print(f"Balance: ${account.balance:,.2f}")
print(f"Equity: ${account.equity:,.2f}")
print(f"Margin: ${account.margin:,.2f}")
print(f"Free Margin: ${account.margin_free:,.2f}")
print(f"Profit: ${account.profit:,.2f}")
print(f"Leverage: 1:{account.leverage}")
# Open positions
print("\n" + "=" * 50)
print("OPEN POSITIONS")
print("=" * 50)
positions = mt5.positions_get()
if positions:
for pos in positions:
print(f"#{pos.ticket} | {'BUY' if pos.type == 0 else 'SELL'} {pos.volume} {pos.symbol}")
print(f" Open: {pos.price_open:.2f} | Current: {pos.price_current:.2f}")
print(f" SL: {pos.sl:.2f} | TP: {pos.tp:.2f}")
print(f" Profit: ${pos.profit:,.2f}")
print()
else:
print("No open positions")
# Recent history
print("=" * 50)
print("RECENT DEALS (Last 10)")
print("=" * 50)
from datetime import datetime, timedelta
deals = mt5.history_deals_get(datetime.now() - timedelta(days=1), datetime.now())
if deals:
for deal in deals[-10:]:
deal_type = "BUY" if deal.type == 0 else "SELL" if deal.type == 1 else "OTHER"
print(f"#{deal.ticket} | {deal_type} {deal.volume} @ {deal.price:.2f} | Profit: ${deal.profit:,.2f}")
else:
print("No recent deals")
mt5.shutdown()
+52
View File
@@ -0,0 +1,52 @@
"""Quick status check script."""
# Run from project root: python scripts/check_status.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import MetaTrader5 as mt5
from dotenv import load_dotenv
from datetime import datetime, timedelta
load_dotenv()
mt5.initialize()
mt5.login(
int(os.getenv('MT5_LOGIN')),
os.getenv('MT5_PASSWORD'),
os.getenv('MT5_SERVER')
)
# Account info
info = mt5.account_info()
print('='*50)
print('ACCOUNT STATUS')
print('='*50)
print(f'Balance: ${info.balance:,.2f}')
print(f'Equity: ${info.equity:,.2f}')
print(f'Profit: ${info.profit:,.2f}')
print(f'Margin: ${info.margin:,.2f}')
# Open positions
positions = mt5.positions_get(symbol='XAUUSD')
print(f'\nOpen Positions: {len(positions) if positions else 0}')
if positions:
total_profit = 0
for pos in positions:
total_profit += pos.profit
ptype = "BUY" if pos.type==0 else "SELL"
print(f' #{pos.ticket}: {ptype} {pos.volume} @ {pos.price_open:.2f} | P/L: ${pos.profit:.2f}')
print(f' Total Floating: ${total_profit:.2f}')
# Recent closed trades
history = mt5.history_deals_get(datetime.now() - timedelta(days=1), datetime.now())
if history:
closed_trades = [d for d in history if d.profit != 0]
print(f'\nClosed Trades (24h): {len(closed_trades)}')
total_closed = 0
for deal in closed_trades[-10:]:
total_closed += deal.profit
result = "WIN" if deal.profit > 0 else "LOSS"
print(f' #{deal.ticket}: {deal.symbol} ${deal.profit:+.2f} [{result}]')
print(f' Total Closed P/L: ${total_closed:+.2f}')
mt5.shutdown()
+58
View File
@@ -0,0 +1,58 @@
"""Close all open positions."""
# Run from project root: python scripts/close_positions.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from dotenv import load_dotenv
load_dotenv()
import MetaTrader5 as mt5
# Connect
mt5.initialize(
login=int(os.getenv("MT5_LOGIN")),
password=os.getenv("MT5_PASSWORD"),
server=os.getenv("MT5_SERVER"),
path=os.getenv("MT5_PATH"),
)
# Get open positions
positions = mt5.positions_get()
if positions:
for pos in positions:
print(f"\nClosing #{pos.ticket} | {'BUY' if pos.type == 0 else 'SELL'} {pos.volume} {pos.symbol}")
print(f" Open: {pos.price_open:.2f} | Current: {pos.price_current:.2f}")
print(f" Profit: ${pos.profit:,.2f}")
# Close position
tick = mt5.symbol_info_tick(pos.symbol)
close_price = tick.bid if pos.type == 0 else tick.ask
request = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": pos.symbol,
"volume": pos.volume,
"type": mt5.ORDER_TYPE_SELL if pos.type == 0 else mt5.ORDER_TYPE_BUY,
"position": pos.ticket,
"price": close_price,
"deviation": 20,
"magic": 123456,
"comment": "Manual close",
"type_time": mt5.ORDER_TIME_GTC,
}
result = mt5.order_send(request)
if result.retcode == mt5.TRADE_RETCODE_DONE:
print(f" CLOSED successfully! Profit: ${pos.profit:,.2f}")
else:
print(f" Failed to close: {result.comment} (code: {result.retcode})")
else:
print("No open positions")
# Check final balance
account = mt5.account_info()
print(f"\n{'='*50}")
print(f"Final Balance: ${account.balance:,.2f}")
print(f"Final Equity: ${account.equity:,.2f}")
mt5.shutdown()
+100
View File
@@ -0,0 +1,100 @@
"""Get real trading history from MT5."""
# Run from project root: python scripts/get_trade_history.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from datetime import datetime, timedelta
from dotenv import load_dotenv
load_dotenv()
import MetaTrader5 as mt5
if not mt5.initialize():
print('MT5 init failed')
exit()
if not mt5.login(int(os.getenv('MT5_LOGIN')), os.getenv('MT5_PASSWORD'), os.getenv('MT5_SERVER')):
print('MT5 login failed')
exit()
# Get account info
account = mt5.account_info()
print(f'Account: {account.login}')
print(f'Balance: ${account.balance:,.2f}')
print(f'Equity: ${account.equity:,.2f}')
print()
# Get trade history (last 14 days)
from_date = datetime.now() - timedelta(days=14)
to_date = datetime.now() + timedelta(days=1)
deals = mt5.history_deals_get(from_date, to_date)
print(f'Total deals in last 14 days: {len(deals) if deals else 0}')
print()
if deals:
# Group by position to calculate trade results
trades = {}
for deal in deals:
if deal.position_id > 0:
if deal.position_id not in trades:
trades[deal.position_id] = []
trades[deal.position_id].append(deal)
print('=' * 70)
print('REAL TRADING HISTORY (Last 14 days)')
print('=' * 70)
total_profit = 0
wins = 0
losses = 0
trade_list = []
for pos_id, pos_deals in trades.items():
if len(pos_deals) >= 2:
# Has entry and exit
entry = next((d for d in pos_deals if d.entry == 0), None) # DEAL_ENTRY_IN
exit_deal = next((d for d in pos_deals if d.entry == 1), None) # DEAL_ENTRY_OUT
if entry and exit_deal:
profit = exit_deal.profit
direction = 'BUY' if entry.type == 0 else 'SELL'
entry_time = datetime.fromtimestamp(entry.time)
exit_time = datetime.fromtimestamp(exit_deal.time)
result = 'WIN' if profit > 0 else 'LOSS'
if profit > 0:
wins += 1
else:
losses += 1
total_profit += profit
trade_list.append({
'time': entry_time,
'direction': direction,
'lot': entry.volume,
'profit': profit,
'result': result
})
# Sort by time and print
trade_list.sort(key=lambda x: x['time'])
for t in trade_list[-50:]: # Last 50 trades
print(f" {t['time']} | {t['direction']} | Lot: {t['lot']} | ${t['profit']:+.2f} [{t['result']}]")
print()
print('=' * 70)
print('REAL TRADING SUMMARY')
print('=' * 70)
total_trades = wins + losses
win_rate = (wins / total_trades * 100) if total_trades > 0 else 0
avg_profit = total_profit / total_trades if total_trades > 0 else 0
print(f' Total Trades : {total_trades}')
print(f' Winning Trades : {wins}')
print(f' Losing Trades : {losses}')
print(f' Win Rate : {win_rate:.1f}%')
print(f' Total P/L : ${total_profit:+,.2f}')
print(f' Average/Trade : ${avg_profit:+.2f}')
mt5.shutdown()
+60
View File
@@ -0,0 +1,60 @@
"""Modify TP of open positions to closer targets."""
# Run from project root: python scripts/modify_tp.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from dotenv import load_dotenv
load_dotenv()
import MetaTrader5 as mt5
# Connect
mt5.initialize(
login=int(os.getenv("MT5_LOGIN")),
password=os.getenv("MT5_PASSWORD"),
server=os.getenv("MT5_SERVER"),
path=os.getenv("MT5_PATH"),
)
# Get current tick
tick = mt5.symbol_info_tick("XAUUSD")
current_price = tick.bid
print(f"Current price: {current_price:.2f}")
# Get open positions
positions = mt5.positions_get()
if positions:
for pos in positions:
print(f"\n#{pos.ticket} | {'BUY' if pos.type == 0 else 'SELL'} {pos.volume} {pos.symbol}")
print(f" Open: {pos.price_open:.2f} | Current: {pos.price_current:.2f}")
print(f" Current SL: {pos.sl:.2f} | Current TP: {pos.tp:.2f}")
print(f" Profit: ${pos.profit:,.2f}")
# Set TP 5 points above current to lock in profits
if pos.type == 0: # BUY
new_tp = current_price + 5 # 5 points above current for quick TP
new_sl = pos.price_open - 10 # Tighter stop loss (protect profit)
else: # SELL
new_tp = current_price - 5
new_sl = pos.price_open + 10
print(f" New SL: {new_sl:.2f} | New TP: {new_tp:.2f}")
# Modify position
request = {
"action": mt5.TRADE_ACTION_SLTP,
"symbol": pos.symbol,
"position": pos.ticket,
"sl": new_sl,
"tp": new_tp,
}
result = mt5.order_send(request)
if result.retcode == mt5.TRADE_RETCODE_DONE:
print(f" MODIFIED successfully!")
else:
print(f" Failed to modify: {result.comment} (code: {result.retcode})")
else:
print("No open positions")
mt5.shutdown()