| id |
title |
type |
status |
priority |
epic |
project |
version |
created_date |
updated_date |
task_reference |
| ET-ML-013 |
MSA (Market Structure Analysis) Strategy |
Technical Specification |
Approved |
Alta |
OQI-006 |
trading-platform |
1.0.0 |
2026-01-25 |
2026-01-25 |
TASK-2026-01-25-ML-TRAINING-ENHANCEMENT |
ET-ML-013: MSA (Market Structure Analysis) Strategy
Metadata
| Campo |
Valor |
| ID |
ET-ML-013 |
| Epica |
OQI-006 - Senales ML |
| Tipo |
Especificacion Tecnica |
| Version |
1.0.0 |
| Estado |
Aprobado |
| Ultima actualizacion |
2026-01-25 |
| Tarea Referencia |
TASK-2026-01-25-ML-TRAINING-ENHANCEMENT |
Resumen
La estrategia MSA (Market Structure Analysis) aplica conceptos de ICT/SMC (Inner Circle Trader / Smart Money Concepts) mediante machine learning. Utiliza XGBoost para predecir la direccion del proximo BOS (Break of Structure), reacciones en POI (Points of Interest), y probabilidad de continuacion de estructura.
Caracteristicas Clave
- Arquitectura XGBoost: Tres clasificadores especializados
- Features ICT/SMC: BOS, CHoCH, FVG, Order Blocks, Liquidity
- Predicciones Multiple: Direccion BOS, reaccion POI, continuacion
- GNN Opcional: Para relaciones entre swing points
Conceptos ICT/SMC
Terminologia Clave
| Concepto |
Descripcion |
Uso en Trading |
| BOS |
Break of Structure - Ruptura de estructura |
Confirmacion de tendencia |
| CHoCH |
Change of Character - Cambio de caracter |
Reversion de tendencia |
| FVG |
Fair Value Gap - Hueco de valor justo |
Zonas de reversion |
| Order Block |
Vela institucional antes de movimiento |
Soporte/resistencia |
| Liquidity |
Zonas con stop losses |
Objetivos de precio |
| POI |
Point of Interest |
Zonas de entrada |
Estructura de Mercado
HH (Higher High)
/
HL /
/ /
LH / / <-- CHoCH (cambio a alcista)
/ / /
LL / /
\ /
\ /
BOS (ruptura)
Arquitectura
Diagrama de Alto Nivel
┌─────────────────────────────────────────────────────────────────────────┐
│ MSA MODEL │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Input: OHLCV Data │
│ └── Structure Detection Pipeline │
│ │ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ STRUCTURE DETECTOR │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Swing Point │──▶│ HH/HL/LH/LL │──▶│ BOS/CHoCH Detection │ │ │
│ │ │ Detection │ │ Classification│ │ │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ FVG │ │ Order Block │ │ Liquidity Level │ │ │
│ │ │ Detection │ │ Detection │ │ Detection │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ MSA FEATURE ENGINEER │ │
│ │ │ │
│ │ Features: 60+ structure-based features │ │
│ │ - Swing point distances │ │
│ │ - BOS/CHoCH counts and recency │ │
│ │ - FVG distances and fill rates │ │
│ │ - Order Block strengths │ │
│ │ - Premium/Discount zones │ │
│ │ - Liquidity imbalances │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ XGBOOST CLASSIFIERS (3) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ BOS Direction Classifier │ │ │
│ │ │ Classes: neutral (0), bullish (1), bearish (2) │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ POI Reaction Classifier │ │ │
│ │ │ Binary: no_reaction (0), reaction (1) │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ Structure Continuation Classifier │ │ │
│ │ │ Binary: reversal (0), continuation (1) │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Output: MSAPrediction │
│ - next_bos_direction: 'bullish' | 'bearish' | 'neutral' │
│ - poi_reaction_prob: float │
│ - structure_continuation_prob: float │
│ - trading_bias: 'LONG_BIAS' | 'SHORT_BIAS' | 'NEUTRAL' │
└─────────────────────────────────────────────────────────────────────────┘
Componente GNN Opcional
class SwingPointGNN:
"""GNN para modelar relaciones entre swing points"""
# Nodos: swing points (high/low)
# Edges: relaciones temporales y de precio
# Output: embeddings para cada swing point
input_dim: 8 # Features por nodo
hidden_dim: 32
output_dim: 16
n_layers: 2
Feature Engineering
Structure Detector
El StructureDetector identifica todos los elementos de estructura:
class StructureDetector:
def __init__(self, swing_order: int = 5):
self.swing_order = swing_order
def analyze(self, df: pd.DataFrame) -> StructureAnalysis:
# Detectar swing points
swing_highs, swing_lows = self.detect_swing_points(df)
# Clasificar HH/HL/LH/LL
classified_highs, classified_lows = self.classify_swings(...)
# Detectar eventos de estructura
bos_events = self.detect_break_of_structure(...)
choch_events = self.detect_change_of_character(...)
# Detectar POIs
fvgs = self.detect_fair_value_gaps(df)
order_blocks = self.detect_order_blocks(df, bos_events)
liquidity = self.detect_liquidity_levels(...)
return StructureAnalysis(...)
Categories de Features (60+)
1. Swing Point Features
Swing Features:
dist_to_swing_high: Distancia al ultimo swing high
dist_to_swing_low: Distancia al ultimo swing low
hh_count: Count de Higher Highs en lookback
hl_count: Count de Higher Lows
lh_count: Count de Lower Highs
ll_count: Count de Lower Lows
last_swing_type: 1=high, -1=low
swing_structure_score: (HH+HL-LH-LL) / 10
2. BOS/CHoCH Features
BOS_CHoCH Features:
bos_bullish_count: Count de BOS alcistas
bos_bearish_count: Count de BOS bajistas
choch_bullish_count: Count de CHoCH alcistas
choch_bearish_count: Count de CHoCH bajistas
bars_since_bos: Candles desde ultimo BOS
bars_since_choch: Candles desde ultimo CHoCH
last_bos_direction: 1=bullish, -1=bearish
last_choch_direction: 1=bullish, -1=bearish
bos_net_bias: bullish - bearish
has_recent_choch: CHoCH en ultimas 20 velas
3. FVG Features
FVG Features:
bullish_fvg_count: Count de FVGs alcistas
bearish_fvg_count: Count de FVGs bajistas
unfilled_fvg_count: FVGs sin llenar
dist_to_nearest_fvg: Distancia al FVG mas cercano
nearest_fvg_type: 1=bullish, -1=bearish
in_fvg: Precio dentro de FVG
fvg_fill_rate: Tasa de llenado de FVGs
fvg_net_bias: bullish - bearish
4. Order Block Features
Order_Block Features:
bullish_ob_count: Count de OB alcistas
bearish_ob_count: Count de OB bajistas
valid_ob_count: OB validos (no rotos)
dist_to_nearest_ob: Distancia al OB mas cercano
nearest_ob_type: 1=bullish, -1=bearish
in_ob: Precio dentro de OB
ob_strength_avg: Fuerza promedio de OB
ob_net_bias: bullish - bearish
5. Premium/Discount Zone Features
Zone Features:
position_in_range: 0-1 posicion en rango
dist_to_equilibrium: Distancia a equilibrio
in_premium: Precio en zona premium
in_discount: Precio en zona discount
dist_to_premium: Distancia a zona premium
dist_to_discount: Distancia a zona discount
6. Liquidity Features
Liquidity Features:
equal_highs_count: Count de equal highs
equal_lows_count: Count de equal lows
dist_to_nearest_liquidity: Distancia a liquidez
liquidity_above: Fuerza de liquidez arriba
liquidity_below: Fuerza de liquidez abajo
liquidity_imbalance: (above - below) / (above + below + 1)
7. POI Distance Features
POI Features:
dist_to_nearest_poi: Distancia al POI mas cercano
nearest_poi_type: Tipo de POI (OB, FVG, swing, liquidity)
in_poi: Precio dentro de un POI
poi_count_nearby: POIs dentro del 1%
8. Trend Features
Trend Features:
bullish_structure_score: (HH + HL) / total_swings
bearish_structure_score: (LH + LL) / total_swings
structure_trend_bias: bullish - bearish
Training Pipeline
Fase 1: Estructura Analysis
# Analizar estructura de mercado
detector = StructureDetector(swing_order=5)
analysis = detector.analyze(df)
# Preparar features
engineer = MSAFeatureEngineer(swing_order=5, lookback_periods=50)
features = engineer.compute_structure_features(df)
Fase 2: Label Generation
def generate_labels(df: pd.DataFrame, forward_bars: int = 12):
"""Generar labels para entrenamiento"""
# Label 1: Direccion del proximo BOS
y_bos = compute_next_bos_direction(df, forward_bars)
# Label 2: Reaccion en POI actual
y_poi = label_poi_reactions(df, pois, forward_bars)
# Label 3: Continuacion de estructura
y_continuation = label_structure_continuation(df, forward_bars)
return y_bos, y_poi, y_continuation
Fase 3: Training XGBoost
model = MSAModel(config)
metrics = model.fit(
X_train,
y_bos=y_bos_train,
y_poi=y_poi_train,
y_continuation=y_continuation_train,
X_val=X_val,
y_bos_val=y_bos_val,
y_poi_val=y_poi_val,
y_continuation_val=y_continuation_val
)
XGBoost Configuration
xgb_config = {
'n_estimators': 200,
'max_depth': 6,
'learning_rate': 0.05,
'subsample': 0.8,
'colsample_bytree': 0.8,
'min_child_weight': 3,
'gamma': 0.1,
'reg_alpha': 0.1,
'reg_lambda': 1.0
}
# BOS: multi-class (3 classes)
bos_params = {**xgb_config, 'objective': 'multi:softprob', 'num_class': 3}
# POI: binary
poi_params = {**xgb_config, 'objective': 'binary:logistic'}
# Continuation: binary
cont_params = {**xgb_config, 'objective': 'binary:logistic'}
Metricas de Evaluacion
Metricas BOS Direction
| Metrica |
Descripcion |
Target |
| BOS Accuracy |
Precision general |
>= 55% |
| Macro F1 |
F1 promedio por clase |
>= 0.50 |
| Per-Class F1 |
F1 por clase |
Balanced |
Metricas POI Reaction
| Metrica |
Descripcion |
Target |
| POI Accuracy |
Precision en reacciones |
>= 60% |
| POI Precision |
True positives / Predicted |
>= 55% |
| POI Recall |
True positives / Actual |
>= 60% |
| POI F1 |
Balance |
>= 0.55 |
Metricas Continuation
| Metrica |
Descripcion |
Target |
| Continuation Accuracy |
Precision en continuacion |
>= 60% |
| Continuation F1 |
F1 score |
>= 0.55 |
API y Uso
Clase Principal: MSAModel
from models.strategies.msa import MSAModel, MSAPrediction
# Configuracion
config = {
'n_estimators': 200,
'max_depth': 6,
'learning_rate': 0.05,
'use_gnn': False # Optional GNN component
}
# Inicializar modelo
model = MSAModel(config, use_gpu=True)
# Entrenar
metrics = model.fit(
X_train, y_bos, y_poi, y_continuation,
X_val, y_bos_val, y_poi_val, y_continuation_val
)
# Prediccion
predictions = model.predict(X_new)
for pred in predictions:
print(f"Next BOS: {pred.next_bos_direction}")
print(f"POI Reaction: {pred.poi_reaction_prob:.2%}")
print(f"Trading Bias: {pred.trading_bias}")
Clase MSAPrediction
@dataclass
class MSAPrediction:
# BOS prediction
next_bos_direction: str # 'bullish', 'bearish', 'neutral'
bos_confidence: float # 0 to 1
bos_probabilities: Dict[str, float]
# POI reaction
poi_reaction_prob: float # 0 to 1
poi_reaction_direction: str # 'bullish', 'bearish', 'none'
# Structure continuation
structure_continuation_prob: float
expected_structure: str # 'bullish_continuation', 'bearish_continuation', 'reversal'
@property
def trading_bias(self) -> str:
"""Get overall trading bias"""
if self.bos_confidence >= 0.7:
if self.next_bos_direction == 'bullish':
return 'LONG_BIAS'
elif self.next_bos_direction == 'bearish':
return 'SHORT_BIAS'
return 'NEUTRAL'
@property
def signal_strength(self) -> float:
"""Calculate overall signal strength 0-1"""
bos_factor = self.bos_confidence if self.next_bos_direction != 'neutral' else 0
poi_factor = self.poi_reaction_prob * 0.5
cont_factor = self.structure_continuation_prob * 0.3
return min(1.0, bos_factor + poi_factor + cont_factor)
Feature Importance
# Obtener importancia de features por clasificador
importance = model.get_feature_importance(top_n=20)
print("BOS Direction - Top Features:")
for feat, imp in importance['bos'].items():
print(f" {feat}: {imp:.4f}")
print("POI Reaction - Top Features:")
for feat, imp in importance['poi'].items():
print(f" {feat}: {imp:.4f}")
Estructura de Archivos
apps/ml-engine/src/models/strategies/msa/
├── __init__.py
├── model.py # MSAModel, MSAPrediction, MSAMetrics
├── feature_engineering.py # MSAFeatureEngineer (60+ features)
├── structure_detector.py # StructureDetector (BOS, CHoCH, FVG, OB)
├── gnn_component.py # Optional SwingPointGNN
└── trainer.py # MSATrainer
Estrategias de Trading
Entry Signals
def generate_entry_signal(pred: MSAPrediction) -> Optional[Dict]:
"""Generar senal de entrada basada en MSA"""
# Long Setup
if (pred.next_bos_direction == 'bullish' and
pred.bos_confidence >= 0.7 and
pred.poi_reaction_prob >= 0.6 and
pred.structure_continuation_prob >= 0.6):
return {
'direction': 'LONG',
'confidence': pred.signal_strength,
'reason': 'MSA Bullish Confluence'
}
# Short Setup
if (pred.next_bos_direction == 'bearish' and
pred.bos_confidence >= 0.7 and
pred.poi_reaction_prob >= 0.6 and
pred.structure_continuation_prob >= 0.6):
return {
'direction': 'SHORT',
'confidence': pred.signal_strength,
'reason': 'MSA Bearish Confluence'
}
return None
POI-Based Entry
def check_poi_entry(price: float, pred: MSAPrediction) -> Optional[Dict]:
"""Verificar entrada en POI"""
# Si estamos en un POI con alta probabilidad de reaccion
if pred.poi_reaction_prob >= 0.7:
direction = 'LONG' if pred.poi_reaction_direction == 'bullish' else 'SHORT'
return {
'type': 'POI_REACTION',
'direction': direction,
'confidence': pred.poi_reaction_prob
}
return None
Consideraciones de Produccion
Real-Time Structure Analysis
class MSARealtime:
def __init__(self, model_path: str, swing_order: int = 5):
self.model = MSAModel.load(model_path)
self.detector = StructureDetector(swing_order=swing_order)
self.engineer = MSAFeatureEngineer(swing_order=swing_order)
self.buffer = deque(maxlen=200)
def on_candle(self, candle: Dict) -> Optional[MSAPrediction]:
self.buffer.append(candle)
if len(self.buffer) >= 100:
df = pd.DataFrame(list(self.buffer))
features = self.engineer.compute_structure_features(df)
return self.model.predict_single(features.iloc[-1:])
return None
Caching de Structure Analysis
# La estructura no cambia frecuentemente
# Cache por 5-10 candles
@cached(ttl=60) # 5 candles de 5 minutos
def get_structure_analysis(symbol: str) -> StructureAnalysis:
df = get_recent_data(symbol, bars=200)
return detector.analyze(df)
Performance
| Operacion |
Tiempo |
Notas |
| Structure detection |
50ms |
200 bars |
| Feature engineering |
30ms |
60+ features |
| XGBoost prediction |
5ms |
3 classifiers |
| Total |
~85ms |
Per prediction |
Referencias
Autor: ML-Specialist (NEXUS v4.0)
Fecha: 2026-01-25