# FeatureGeneratorByLeoConfig - Especificación del Lenguaje > **Autor:** Niquel Mendoza y Leo --- ## Descripción General **FeatureGeneratorByLeoConfig** es un DSL declarativo diseñado para definir conjuntos de *features* que la clase (CAiLeoMulyiFeatureGen) transforma en un **vector** o una **matriz** de valores numéricos. Su principal caso de uso es la generación de datos de entrada para modelos ML dentro de plataformas MT5. ## Extensiones de archivo - `.fgblc`: Tanto para archivos y codigo en MD --- ## Conceptos Fundamentales | Concepto | Descripción | |---|---| | **Feature** | Clase que produce uno o varios valores numéricos en cada tick o barra | | **Vector** | Salida de una sola fila: cada feature ocupa una columna | | **Matrix** | Salida de múltiples filas: cada contexto local ocupa una o varias filaso son acopladas (varias features en una columna) | | **Índice (`idx`)** | Número entero que parametriza la feature (p.ej. período de un indicador) | | **Contexto Global** | Bloque `@New` que declara si la salida es Vector o Matrix | | **Contexto Local** | Bloque `#` dentro de un `@New` que define cómo se asignan los índices | | **Prefijo** | Cadena opcional que diferencia dos instancias de la misma feature | --- ## Sintaxis del Lenguaje La estructura general de un archivo `.fgblc` es: ```fgblc name = [Generador de features] @Config { cols=37; // Siempre se define el numero de columnas primero } @New Vector { #Normal(idx=) { [Feature1][prefijo](param1|param2|...) [Feature2][prefijo](param1|...) } } ``` ### Nombre del generador "name" En caso que la clase CAiLeoMulyiFeatureGen se inicialize por archivo (`InitByFile(...)`)se requeria que la primera linea del archivo se ubique el nombre del Generador, entre [], ejemplo: ```fgblc name = [Generador de features] ``` En caso se use `Init(const string& name, const string& src)` uno debera de pasar el nombre del generador.. aparte **no dentro del DSL** ### Configuración `@Config` Define el número de columnas (features) que tendrá cada fila de la salida. ```fgblc cols = 4; ``` > **Obligatorio.** Debe ser el primer elemento del archivo. El parser rechazará cualquier script que no comience con este token. --- ### Contexto Global `@New` Declara el tipo de contenedor de salida y abre un bloque de definición. #### Vector Genera una salida de una sola fila. ```fgblc @New Vector { // contextos locales y features aquí } ``` #### Matrix Genera una salida de múltiples filas. Requiere especificar el número de filas. ```fgblc @New Matrix(rows=) { // contextos locales y features aquí } ``` | Parámetro | Tipo | Descripción | |---|---|---| | `rows` | `int` | Número de filas que tendrá la matriz. Cada contexto local debe coincidir con este número. | --- ### Contexto Local `#` Define cómo se asignan los índices a las features dentro de su bloque. Se escribe dentro de un `@New`. Los contextos locales varían según si el padre (contexto global) es **Vector** o **Matrix**. #### Dentro de `@New Vector` | Sintaxis | Tipo | Descripción | |---|---|---| | `#Normal(idx=)` | Índice fijo | Todas las features del bloque reciben el mismo índice `n` | | `#Custom([i1,i2,...])` | Índice por feature | Cada feature recibe el índice correspondiente de la lista, en orden | ```fgblc // Todas las features reciben idx=1 #Normal(idx=1) { [RSI][_rsi14](period=14|price=CLOSE) [EMA][_ema](period=50|price=CLOSE) } // Cada feature recibe su propio índice #Custom([1,2,3]) { [RSI][a]() // idx=1 [RSI][b]() // idx=2 [RSI][c]() // idx=3 } ``` #### Dentro de `@New Matrix` | Sintaxis | Tipo | Descripción | |---|---|---| | `#Matrix([i1,i2,...])` | Índices básicos | Una lista de índices, uno por fila. El número de elementos debe coincidir con `rows` | | `#Generate([start,step,len])` | Índices generados | Genera automáticamente la lista: `start`, `start+step`, `start+step*2`, ... | | `#Custom([i1,i2,...])` | Índices multi | Asigna índices distintos a features en una misma fila (acoplamiento de features) | ```fgblc // Matrix con índices explícitos [1,2,3] #Matrix([1,2,3]) { [RSI][](period=14|price=CLOSE) } // Matrix con índices generados: start=1, step=1, len=5 → [1,2,3,4,5] #Generate([1,1,5]) { [EMA][](period=50|price=CLOSE) } // Custom: varias features con índices distintos por fila #Custom([10,20,30]) { [RSI][a]() // idx=10 [EMA][b]() // idx=20 [ATR][c]() // idx=30 } ``` --- ### Feature Unidad básica del lenguaje. Representa una instancia de una clase que produce datos. ```fgblc [NombreFeature][Prefijo](param1|param2|...|paramN) ``` | Parte | Descripción | |---|---| | `NombreFeature` | Nombre registrado de la feature en el Factory | | `Prefijo` | Cadena libre para distinguir dos instancias del mismo tipo. Puede estar vacío `[]` | | `param1\|...\|paramN` | Lista de parámetros separados por `\|`. El orden debe coincidir con el esperado por la implementación | **Ejemplos:** ```fgblc [RSI][_periodo14](period=14|price=CLOSE|timeframe=H1) [EMA][](period=50|price=CLOSE|timeframe=M15) [ATR][high_vol](period=20|timeframe=D1) ``` --- ### Comentarios Se admiten comentarios de línea al estilo C++: ```fgblc // Esto es un comentario y será ignorado por el parser @Config = 3; // También al final de una línea ``` > Los comentarios de bloque (`/* ... */`) **no están soportados**. --- ## Tipos de Salida El parser determina automáticamente el tipo de salida según el número de filas declaradas: | Condición | Tipo de salida | Enumeración | |---|---|---| | `rows == 1` | Vector (una fila) | `AIDATALEO_GEN_VECTOR` | | `rows > 1` | Matrix (varias filas) | `AIDATALEO_GEN_MATRIX` | --- ## Crear una Feature Personalizada ### Clase base `CAiDataLeoFeature` Toda feature debe heredar de `CAiDataLeoFeature`: ```cpp class MiFeature : public CAiDataLeoFeature { public: MiFeature() : CAiDataLeoFeature( 2, // número de parámetros en el DSL "MiFeature",// nombre (debe coincidir con el Factory) true, // soporta índices > 1 false // no usa OnNewBarM1 ) {} protected: // Funcion de inicizalizacion bool OnInitEvent(AiDataByLeoDataParamsParser& config) override final { int period = config.ReadNumber(0); string symbol = config.ReadStr(1); // inicialización... return true; } public: // Obtencion de valor vector GetValue(const datetime curr_time, const double bid, const double ask) override final { m_v[0] = /* calcular valor */; return m_v; } // Aparte de esta funcion se puede tener eventos extendidos todo depende de AIDATA_LEO_FEATURE_FIRST, por defecto se disponen // De los eventos OnNewBarM1, OnNewDay, OnNewWeek, OnNewMonth }; ``` --- ## Ejemplos Completos ### Ejemplo 1 - Vector simple con índice fijo ```fgblc // 3 features, todas con idx=1 @ Config { cols=3; } @New Vector { #Normal(idx=1) { [RSI][](period=14|price=0|tf=H1) [EMA][fast](period=20|price=0|tf=H1) [EMA][slow](period=50|price=0|tf=H1) } } ``` --- ### Ejemplo 2 - Vector con índices distintos por feature ```fgblc // 3 instancias de RSI con períodos diferentes @ Config { cols=3; } @New Vector { #Custom([7,14,21]) { [RSI][p7](period=0|price=0|tf=H1) // idx=7 [RSI][p14](period=0|price=0|tf=H1) // idx=14 [RSI][p21](period=0|price=0|tf=H1) // idx=21 } } ``` --- ### Ejemplo 3 - Matrix con índices explícitos ```fgblc // Matrix de 3 filas x 2 columnas @ Config { cols=2; } @New Matrix(rows=3) { #Matrix([1,2,3]) { [EMA][](period=20|price=CLOSE|tf=H1) [ATR][](period=14|tf=H1) } } ``` --- ### Ejemplo 4 - Matrix con índices generados automáticamente ```fgblc // Genera índices [0,1,2,3,4] (start=0, step=1, len=5) @ Config { cols=1; } @New Matrix(rows=5) { #Generate([0,1,5]) { [Candle][](tf=M15) } } ``` --- ### Ejemplo 5 - Múltiples contextos locales en una Matrix ```fgblc @ Config { cols=2; } @New Matrix(rows=4) { // Filas 1-2 con índices [10,20] #Matrix([10,20]) { [RSI][a](period=14|price=CLOSE|tf=H1) [EMA][a](period=50|price=CLOSE|tf=H1) } // Filas 3-4 con índices custom #Custom([5,15]) { [ATR][b](period=14|tf=H4) // idx=5 [ATR][c](period=14|tf=H4) // idx=15 } } ``` --- ## Notas finales - El codigo se parsea **de arriba hacia abajo**. El orden de declaración determina la posición en el resultado: la primera feature ocupa la columna `0`. - En las **matrices**, la estructura crece hacia abajo (en filas). Cada contexto local `#Matrix` o `#Generate` suma filas al total. - En modo `#Custom` dentro de una Matrix, las features se **acoplan en columnas** dentro de una misma fila en lugar de apilarse. - El número de features en un contexto local no puede superar el valor de `cols`. El parser lo rechazará con un error crítico. - Una feature con `support_idx = false` solo acepta `idx` con valor `0` o `1`. Un índice mayor provocará error.