
Desarrollo de un sistema de repetición (Parte 77): Un nuevo Chart Trade (IV)
Introducción
En el artículo anterior «Desarrollo de un sistema de repetición (Parte 76): Un nuevo Chart Trade (III)», expliqué la parte realmente importante del código DispatchMessage y comencé a explicar cómo deberá crearse el proceso de comunicación o protocolo de comunicación.
Antes de empezar realmente este artículo, vamos a hacer un pequeño cambio en el mismo código que se muestra en el artículo anterior. Todo lo explicado allí sigue siendo válido. Ahora vamos al tema del cambio que se va a realizar, ya que el verdadero interés de este artículo será otro.
Estabilizar aún más el código DispatchMessage
Por esta razón, debido a algún problema en la interacción entre el indicador de mouse y Chart Trade, tenemos que hacer algún cambio. De hecho, no logro entender el motivo real por el que la interacción falla a veces. Sin embargo, si se usa el fragmento de abajo, el problema desaparece.
259. //+------------------------------------------------------------------+ 260. void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam) 261. { 262. #define macro_AdjustMinX(A, B) { \ 263. B = (A + m_Info.Regions[MSG_TITLE_IDE].w) > x; \ 264. mx = x - m_Info.Regions[MSG_TITLE_IDE].w; \ 265. A = (B ? (mx > 0 ? mx : 0) : A); \ 266. } 267. #define macro_AdjustMinY(A, B) { \ 268. B = (A + m_Info.Regions[MSG_TITLE_IDE].h) > y; \ 269. my = y - m_Info.Regions[MSG_TITLE_IDE].h; \ 270. A = (B ? (my > 0 ? my : 0) : A); \ 271. } 272. 273. static short sx = -1, sy = -1, sz = -1; 274. static eObjectsIDE obj = MSG_NULL; 275. short x, y, mx, my; 276. double dvalue; 277. bool b1, b2, b3, b4; 278. ushort ev = evChartTradeCloseAll; 279. 280. switch (id) 281. { 282. case CHARTEVENT_CHART_CHANGE: 283. x = (short)ChartGetInteger(GetInfoTerminal().ID, CHART_WIDTH_IN_PIXELS); 284. y = (short)ChartGetInteger(GetInfoTerminal().ID, CHART_HEIGHT_IN_PIXELS); 285. macro_AdjustMinX(m_Info.x, b1); 286. macro_AdjustMinY(m_Info.y, b2); 287. macro_AdjustMinX(m_Info.minx, b3); 288. macro_AdjustMinY(m_Info.miny, b4); 289. if (b1 || b2 || b3 || b4) AdjustTemplate(); 290. break; 291. case CHARTEVENT_MOUSE_MOVE: 292. if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft)) 293. { 294. switch (CheckMousePosition(x = (short)lparam, y = (short)dparam)) 295. { 296. case MSG_MAX_MIN: 297. if (sz < 0) m_Info.IsMaximized = (m_Info.IsMaximized ? false : true); 298. break; 299. case MSG_DAY_TRADE: 300. if ((m_Info.IsMaximized) && (sz < 0)) m_Info.IsDayTrade = (m_Info.IsDayTrade ? false : true); 301. break; 302. case MSG_LEVERAGE_VALUE: 303. if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_LEVERAGE_VALUE, m_Info.Leverage); 304. break; 305. case MSG_TAKE_VALUE: 306. if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_TAKE_VALUE, m_Info.FinanceTake); 307. break; 308. case MSG_STOP_VALUE: 309. if ((m_Info.IsMaximized) && (sz < 0)) CreateObjectEditable(obj = MSG_STOP_VALUE, m_Info.FinanceStop); 310. break; 311. case MSG_TITLE_IDE: 312. if (sx < 0) 313. { 314. DeleteObjectEdit(); 315. ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false); 316. sx = x - (m_Info.IsMaximized ? m_Info.x : m_Info.minx); 317. sy = y - (m_Info.IsMaximized ? m_Info.y : m_Info.miny); 318. } 319. if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, mx); 320. if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, my); 321. if (m_Info.IsMaximized) 322. { 323. m_Info.x = (mx > 0 ? mx : m_Info.x); 324. m_Info.y = (my > 0 ? my : m_Info.y); 325. }else 326. { 327. m_Info.minx = (mx > 0 ? mx : m_Info.minx); 328. m_Info.miny = (my > 0 ? my : m_Info.miny); 329. } 330. break; 331. case MSG_BUY_MARKET: 332. ev = evChartTradeBuy; 333. case MSG_SELL_MARKET: 334. ev = (ev != evChartTradeBuy ? evChartTradeSell : ev); 335. case MSG_CLOSE_POSITION: 336. if ((m_Info.IsMaximized) && (sz < 0)) 337. { 338. string szTmp = StringFormat("%d?%s?%c?%d?%.2f?%.2f", ev, _Symbol, (m_Info.IsDayTrade ? 'D' : 'S'), m_Info.Leverage, 339. FinanceToPoints(m_Info.FinanceTake, m_Info.Leverage), FinanceToPoints(m_Info.FinanceStop, m_Info.Leverage)); 340. PrintFormat("Send %s - Args ( %s )", EnumToString((EnumEvents) ev), szTmp); 341. sz = x; 342. EventChartCustom(GetInfoTerminal().ID, ev, 0, 0, szTmp); 343. } 344. break; 345. } 346. if (sz < 0) 347. { 348. sz = x; 349. AdjustTemplate(); 350. if (obj == MSG_NULL) DeleteObjectEdit(); 351. } 352. }else 353. { 354. sz = -1; 355. if (sx > 0) 356. { 357. ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true); 358. sx = sy = -1; 359. } 360. } 361. break; 362. case CHARTEVENT_OBJECT_ENDEDIT: 363. switch (obj) 364. { 365. case MSG_LEVERAGE_VALUE: 366. case MSG_TAKE_VALUE: 367. case MSG_STOP_VALUE: 368. dvalue = StringToDouble(ObjectGetString(GetInfoTerminal().ID, m_Info.szObj_Editable, OBJPROP_TEXT)); 369. if (obj == MSG_TAKE_VALUE) 370. m_Info.FinanceTake = (dvalue <= 0 ? m_Info.FinanceTake : dvalue); 371. else if (obj == MSG_STOP_VALUE) 372. m_Info.FinanceStop = (dvalue <= 0 ? m_Info.FinanceStop : dvalue); 373. else 374. m_Info.Leverage = (dvalue <= 0 ? m_Info.Leverage : (short)MathFloor(dvalue)); 375. AdjustTemplate(); 376. obj = MSG_NULL; 377. ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Editable); 378. break; 379. } 380. break; 381. case CHARTEVENT_OBJECT_CLICK: 382. if (sparam == m_Info.szObj_Chart) if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft)) switch (obj = CheckMousePosition(x = (short)lparam, y = (short)dparam)) 383. { 384. case MSG_DAY_TRADE: 385. m_Info.IsDayTrade = (m_Info.IsDayTrade ? false : true); 386. DeleteObjectEdit(); 387. break; 388. case MSG_MAX_MIN: 389. m_Info.IsMaximized = (m_Info.IsMaximized ? false : true); 390. DeleteObjectEdit(); 391. break; 392. case MSG_LEVERAGE_VALUE: 393. CreateObjectEditable(obj, m_Info.Leverage); 394. break; 395. case MSG_TAKE_VALUE: 396. CreateObjectEditable(obj, m_Info.FinanceTake); 397. break; 398. case MSG_STOP_VALUE: 399. CreateObjectEditable(obj, m_Info.FinanceStop); 400. break; 401. } 402. if (obj != MSG_NULL) AdjustTemplate(); 403. break; 404. case CHARTEVENT_OBJECT_DELETE: 405. if (sparam == m_Info.szObj_Chart) macro_CloseIndicator(C_Terminal::ERR_Unknown); 406. break; 407. } 408. ChartRedraw(); 409. } 410. //+------------------------------------------------------------------+
Fragmento del fichero C_ChartFloatingRAD.mqh
Observa que hay algunas líneas eliminadas, como las líneas 314 y 341 que se movieron hacia dentro de la prueba de la línea 346 para solucionar un problema que ocurría al hacer clic en algunos controles. Observa que la variable sz, se utiliza en cada uno de los objetos. Esto se observa en las líneas 297, 300, 303, 306 y 309, así como en las pruebas existentes en las líneas 312 y 336.
Al comparar este código con el anterior, se observa que este busca, de hecho, estabilizar la interacción entre el indicador de mouse y Chart Trade, ya que, cuando se cargaba primero el indicador de mouse, algunos controles de Chart Trade no respondían de forma adecuada, por lo que era necesario quitar el indicador del gráfico, y volver a colocarlo después. Solo así los controles de Chart Trade pasaban a responder de manera correcta. Algo extraño, sin duda.
Por esta razón, el evento CHARTEVENT_OBJECT_CLICK, deberá eliminarse del código de procesamiento. Así, todas las líneas entre 381 y 403 deberán ser retiradas del código del artículo anterior. Y, como tales cambios no suponen ninguna diferencia con respecto a lo explicado en el artículo anterior, pasaremos al siguiente tema, que es el principal de este artículo.
Entender la planificación sobre el protocolo de mensajes
Como no sé qué es lo que tú, querido lector, realmente sabes sobre sistemas de comunicación donde hacemos uso de computadoras, voy a asumir que no tienes ningún conocimiento sobre el tema. Si este no es tu caso, lo que voy a explicar probablemente no te aportará ningún conocimiento, por lo que podríamos pasar al siguiente tema.
En el artículo anterior, expliqué por qué necesitas convertir valores numéricos en su correspondiente literal. Es decir, si necesitas transferir el valor binario 0001 0011, deberás transformarlo en una cadena que represente el valor 19, por lo que necesitarás transferir 2 bytes en vez de 1. Aunque pueda parecer poco eficiente, el objetivo no es ser eficiente, sino garantizar que la información se transmita correctamente. Si es posible hacerlo con eficiencia, mejor. Pero lo más importante es que la información sea entendida correctamente en el otro extremo.
Como se explicó en el artículo anterior, vamos a utilizar el campo sparam. Ahora tenemos que pensar en lo siguiente: si la información debe transmitirse dentro de una única cadena, ¿cómo podemos reconocer cuándo termina una información y empieza otra? Esta es la cuestión clave.
Debes idear o planear una forma de hacerlo. Tienes que colocar la información de manera que después puedas recuperarla. Hay diversas formas diferentes y, al mismo tiempo, complementarias de hacerlo. Una de ellas es colocar cada información dentro de un array de tamaño fijo. Estos arrays se concatenarían para formar una cadena que se transmitiría. Este enfoque tiene ventajas y desventajas.
La ventaja es que cualquier información podría obtenerse a partir de un índice, ya que el array tendría siempre un tamaño fijo, lo que facilita el indexado. Sin embargo, del mismo modo que el uso de un array de tamaño fijo facilita el acceso a cualquier información dentro de la cadena, esta se vuelve bastante ineficiente si cada información no hace uso de todo el bloque del array. De hecho, las posiciones vacías ocuparían ancho de banda o, en nuestro caso, memoria.
Para que tú puedas entender mejor, mira la imagen justo abajo:
En esta imagen, el bloque azul corresponde al carácter NULO, que siempre estará presente al final de la cadena y mostrará dónde termina. Observa que hay dos arrays de tamaño cuatro y que en uno de ellos hay posiciones vacías. Es este tipo de situación lo que dificulta el uso de un array de tamaño fijo.
Pero podemos hacer otro enfoque: ¿y si, en vez de colocar un array de tamaño fijo, colocáramos un array que indicara el tamaño de la información esperada? De este modo, la cadena sería mucho más adecuada y facilitaría la búsqueda y el hallazgo de la información que necesitamos. Sin embargo, aunque este enfoque sea muy bueno, tiene un problema. Necesitaríamos codificar más. Al crear más código, necesitamos probarlo. Además, muchas veces, si la información sobrepasa el límite establecido en la implementación, se producirá pérdida de información durante el ensamblaje de la cadena. En el caso perfecto, como se muestra en la imagen de abajo:
Como se puede ver en la primera imagen, el bloque azul indica dónde se encuentra el carácter que marca el final de la cadena. Nota que aquí tenemos una condición perfecta, donde cada color representa información que estará comprimida dentro de la cadena. Aunque en algunos casos complique la descompresión de la cadena, para recuperar la información original de manera integral y correcta, este caso parece bastante adecuado. Sin embargo, en este caso, cada conjunto tendrá un tamaño fijo. Entonces, tendríamos un enfoque mejor que el mostrado en la primera imagen. Sin embargo, tenemos un problema. Y este es: ¿qué pasaría si la información que debería estar en el conjunto verde, en vez de dos bytes, necesitara tres bytes?
Esta sería la peor de las situaciones. Esto se debe a que uno de los bytes se perdería durante el ensamblaje del conjunto verde. Pero puedes pensar así: ¿y si el conjunto verde pudiera crecer para contener ese byte extra? ¿Podríamos hacer esto? No. Si haces esto, toda la información que venga después del conjunto verde quedará comprometida. Y el receptor no podrá comprender que el conjunto verde tiene tres y no dos bytes, que era lo que esperaba.
¿Te das cuenta ahora de que esta parte de la creación del protocolo de comunicación no es tan trivial? Si quien tendrá que decodificar el mensaje espera que cada conjunto tenga un tamaño determinado y, durante la creación del conjunto, cambiamos las reglas, el receptor no podrá entender lo que estamos intentando decir. Por tanto, necesitamos un enfoque un poco diferente.
Entonces, pensemos un poco. ¿Y si, en lugar de crear un bloque de tamaño fijo, creáramos uno de tamaño variable, donde la información pudiera tener el tamaño que quisiera? Esto sería mucho mejor, ¿verdad? En cierto modo, sí, pero tenemos un problema: ¿cómo se le indica al receptor del mensaje cuándo termina un conjunto y empieza otro? Ahora tenemos otro problema que resolver. Y es en este punto donde necesitas pensar con mucho más cuidado, porque si no reflexionas con suficiente calma sobre cómo estás haciendo las cosas, transmitirás un mensaje que el receptor no podrá entender, aunque para ti esté correcto. Pero para el receptor no está tan claro. ¿Cómo es esto?
Piensa en lo siguiente: cada sección del mensaje podrá tener cualquier tamaño, lo que nos permite, virtualmente, transferir cualquier tipo de información. Las informaciones necesitan estar en una determinada secuencia, sea cual sea. Pero la secuencia deberá mantenerse siempre. Hasta este punto, todo bien. No tenemos ningún problema. Excepto el siguiente problema: ¿cómo decir que una sección terminó y otra está comenzando?
Bueno, como dije antes, esta es la parte complicada. Todo dependerá del tipo de datos que colocamos en la cadena. Si utilizas los 255 valores posibles en un byte —de nuevo, debemos evitar el carácter nulo, por eso 255 y no 256—, tendremos un gran problema: cómo indicar que estamos proporcionando otra información dentro del bloque de la cadena. Sin embargo, si reducimos los valores a caracteres entre los valores 32 y 127, tendremos más trabajo con respecto al ensamblaje. No obstante, esto nos permite usar cualquier valor entre 128 y 255 como un carácter de marcado.
No obstante, nosotros podemos limitar las cosas aún más. Podemos usar únicamente los caracteres alfanuméricos para transmitir la información deseada. Esto abre la posibilidad de usar signos de puntuación o caracteres delimitadores para indicar indicar cuándo una información dentro de la cadena completa comienza o termina. ¿Y por qué podemos hacer esto aquí? El motivo es que los datos que necesitamos transmitir son, básicamente, información sobre el nombre del símbolo y algunos valores numéricos, como el nivel de apalancamiento, los valores de take profit o stop loss. Estos se configuran en Chart Trade, pero es necesario transmitirlos al Expert Advisor (EA).
Pero, además de estos valores, que son bastante simples, necesitamos transmitir otro. Aunque MetaTrader 5 hace esto por nosotros. Sin embargo, como quiero asegurar firmemente que las cosas nunca se salgan de control, vamos a transmitir, a lo largo de la cadena, la operación que estamos realizando. Este tipo de cosa no sería necesaria.
Pero quiero que entiendas lo siguiente: no necesitas usar todas las aplicaciones en un único terminal. Puedes crear medios para comunicar, vía protocolo de red, las cosas. Así, en una computadora tendríamos el terminal y, en otra estación de trabajo, podríamos tener todo un sistema de gestión de posiciones y órdenes. De esta forma, incluso un ordenador modesto podría funcionar como si fuera mucho más moderno.
Pero no voy a entrar en estas cuestiones en este momento. La idea aquí es promover y entender cómo la comunicación va, de hecho, a funcionar.
Reunir lo mejor de cada mundo
Lo que vamos a hacer aquí es combinar lo mejor de cada enfoque explicado anteriormente, pero de una manera que permita utilizar los conceptos explicados al final del tema anterior. Es decir, usaremos caracteres alfanuméricos para transmitir la información que necesitamos y, al mismo tiempo, organizaremos las cosas de manera que la información pueda buscarse mediante índice. Pero hay un detalle: la información podrá usar tantos caracteres como sean necesarios para transmitirse de forma completa.
Para entender esto, observa la línea 338 en el fragmento mostrado al inicio de este artículo. Para dejarlo aún más claro, veamos un ejemplo de envío práctico.
En esta imagen, justo arriba, puedes ver un ejemplo real de envío mediante Chart Trade. Pero, ¿qué informa este mensaje loco? Para entenderlo, debemos examinar lo que ocurre en la línea 338 del fragmento. Aunque parezca confuso y bastante disperso, este mensaje sigue un protocolo de envío. De hecho, aquí estamos usando lo mejor de dos mundos. Permite que los bloques dentro de la cadena tengan cualquier tamaño y, al mismo tiempo, indexa de alguna forma la información de la cadena.
Es posible que no estés entendiendo cómo se está produciendo esta indexación. Realmente no es muy evidente. Pero existe. Observa el carácter D dentro del mensaje. Observa que está antecedido y precedido por el mismo carácter y que solo hay un bloque que se está llenando con el carácter D en este punto. Esto no ocurre en ningún otro punto del mensaje. Esto indica que este único carácter puede indexarse de alguna forma. Pero esto quedará más claro después. Por ahora, vamos a entender lo que está ocurriendo.
El primer bloque, que en este mensaje en particular contiene un único carácter, indica qué tipo de operación debe realizarse. Una vez más, MetaTrader 5 informará de esto a nuestro programa EA, como se verá después. Pero aquí estoy considerando el hecho de que Chart Trade realmente se comunicará con el EA de cualquier manera, ya sea a través de la red, por correo electrónico o de cualquier otra forma. Por esta razón, le informo del tipo de operación que deberá ejecutarse.
Un detalle: este valor nueve corresponde al evento de compra a mercado. Sin embargo, podría ser diferente; por ejemplo, si en este bloque tuviéramos el valor once, indicaría el cierre de todas las posiciones. En este caso, el bloque tendría dos caracteres, y no uno, como se ve en este ejemplo. Pero ¿por qué el valor es nueve para compra y once para cierre de las posiciones? De dónde viene este valor? Esta es una pregunta bastante válida. Fíjate que, en la línea 338, el primer valor que se coloca en la cadena es un valor ushort. Pero esto no aclara por qué nueve indica compra y once indica cierre, ¿verdad? De hecho, no lo explica.
Pero fíjate en la línea 278. De dónde viene este valor? Este valor proviene del archivo de cabecera Defines.mqh. Ahora, presta atención. En el archivo Defines.mqh hay una enumeración: EnumEvents. Dicha enumeración comienza en el valor cero e incrementa un valor con cada nuevo elemento. Entonces, contando desde el primer evento (evHideMouse), tenemos el noveno evento (evChartTradeBuy) y el décimo evento (evChartTradeCloseAll). Ahora ya sabes de dónde provienen estos valores que se ven al principio de la cadena. Derivan de la enumeración EnumEvents.
Entonces vamos a continuar. Observa que todos los caracteres de interrogación están marcados en violeta. El carácter NULO, que cierra la cadena, está marcado en azul. Como cada bloque está delimitado por el carácter de interrogación, podemos colocar tantos caracteres alfanuméricos como sean necesarios para enviar el mensaje. Solo que, algunos detalles: este mensaje debe construirse en una secuencia determinada. Recuerda: el receptor espera recibir los datos en un orden determinado. Aunque podamos colocar las informaciones en un orden aleatorio, el receptor no espera esto, al menos en esta versión que voy a mostrar.
Entonces, el próximo bloque de caracteres informará el nombre del símbolo en el que estamos ejecutando la orden. Nuevamente, esto no sería necesario si el EA y Chart Trade estuvieran en un mismo gráfico. Pero estoy considerando que esto no estaría, de hecho, ocurriendo.
Además, más adelante verás que esta información del mensaje se puede usar para hacer otras cosas. En el ejemplo, el símbolo en cuestión es BOVA11, que es un ETF. Esta parte del nombre del símbolo es algo que realmente complicaría las cosas si no usáramos un delimitador. Esto se debe a que existen mercados en los que el nombre del símbolo está compuesto por cuatro caracteres alfanuméricos, mientras que en otros casos podemos tener cinco. En este caso, tenemos cinco caracteres. Sin embargo, incluso en B3 (Bolsa de Brasil) existen diversos símbolos que usan cuatro caracteres.
Y hay una cosa más. Recuerda que la idea es generar un Chart Trade que también pueda utilizarse en el sistema de repetición/simulador. En este caso, el nombre del símbolo puede tener cualquier número de caracteres alfanuméricos. Por este motivo, sería muy bien recibido un bloque de tamaño dinámico.
Ahora, volvemos a nuestro carácter D. En este punto, quiero llamar tu atención para que vuelvas a mirar la línea 338. Observa que, si la operación que se va a realizar no es del tipo que se cierra el mismo día (es decir, si no se trata de day trade), el carácter que estará en este bloque será, de hecho, diferente y será reemplazado por una S. Puedes usar cualquier otro carácter que desees, pero recuerda cambiar esto también en el receptor; de lo contrario, la comunicación será más difícil de realizar, ya que el receptor podría no entender lo que representa la letra o el conjunto de caracteres.
Justo después tenemos un valor literal. En este caso, 250. ¿Qué representa este valor? De nuevo, consulta el código de la línea 338 para entender que este valor es el nivel de apalancamiento deseado. Aquí reside una cuestión interesante. En este caso, estamos usando tres símbolos numéricos para representar el valor de apalancamiento que queremos usar.
Pero ¿no sería mejor usar un valor binario para esto? De hecho, esto parece bastante adecuado, ya que no es posible utilizar un nivel de apalancamiento cero. Sin embargo, existe una condición que lo impide. No me refiero a la condición de que no podamos formatear la cadena con un carácter correspondiente al valor 250, o cualquier otro. Me refiero al problema del símbolo o carácter usado como delimitador. Consulta una tabla ASCII y comprueba cuál es el valor del símbolo de interrogación. Verás que el valor es 63.
Para facilitarte la vida, querido lector, en la imagen abajo estoy poniendo a tu disposición la tabla ASCII, del carácter 0 hasta el carácter 128.
Y ¿por qué es importante este valor 63 para nosotros? El motivo es que cualquier valor de apalancamiento que utilices, incluido el 63, será interpretado por el receptor que mostraré pronto como si fuera un carácter delimitador. Es decir, el receptor no logrará entender que el cuarto bloque se refiere al valor que se usará como nivel de apalancamiento.
Pero entonces puedes pensar: ¿y si modifico esta condición, yendo hacia otro valor? Por ejemplo: si sumo a este nivel de apalancamiento el valor 63, sabiendo que el valor de apalancamiento nunca será igual a cero. Así, el primer valor que, de hecho, se construirá será el 64. ¿Problema resuelto? Me gustaría que las cosas fueran tan simples así. Pero no; tú, al hacer esto — al sumar 63 al valor de apalancamiento — solo estarás, de hecho, posponiendo el problema para otro momento.
Ahora se ha complicado. Porque no lo entiendo. ¿Cómo es eso? Si sumo 63 al valor de apalancamiento, todos los valores siempre serán mayores que 63, sí, de hecho, todos los valores serán mayores que 63, y ahí está la gracia. En programación, ningún valor es, de hecho, infinito. Todo valor está limitado a un número. El número máximo depende del tamaño de la palabra que se utilice. Incluso en un procesador de 64 bits, donde actualmente corre MetaTrader 5, el sistema de gestión está basado en conceptos de 8 bits.
Es decir, incluso usando un procesador de 64 bits, no podrás contar, en términos de caracteres, un valor de 2 elevado a 64, que sería: 18.446.744.073.709.551.615. En realidad, solo se podría contar hasta 255, que es el equivalente a 2 elevado a 8. Pero, ¿por qué? ¿Será que no habría forma de resolver esto? Sí, existen formas de resolverlo. Una de ellas es usar una tabla diferente de la ASCII. Un ejemplo sería utilizar tablas Unicode.
Sin embargo, existe otro problema. La llamada StringFormat no hace uso de la tabla Unicode, al menos no en este momento en que escribo este artículo. Las funciones de cadena de caracteres de MQL5 básicamente siguen los principios de C/C++, es decir, hacen uso de la tabla ASCII. Aunque C/C++ tiene funciones para trabajar con la tabla Unicode, originalmente esto no ocurría.
Por tanto, aunque sumes 63 al valor de apalancamiento, se generará un valor compuesto cada 255 posiciones. Este valor es la combinación de un factor y el valor 63. El factor indica cuántas veces el ciclo de conteo hasta 255 se ha producido. Así que, para que lo entiendas, el valor 575 es la combinación de 2, que es el factor, más 63, que es el valor del conteo actual. Y así sucesivamente.
Entonces, para representar las cosas, necesitarías dos bytes, siendo que el segundo byte siempre sería el valor 63 en algún momento del conteo. El primer byte sería el valor del factor, es decir, cuántas veces el conteo alcanzó el límite máximo permitido, que siempre sería 2 elevado a 8, como expliqué anteriormente. Este tipo de cosa tiene diversas implicaciones matemáticas, pero no las explicaré aquí y ahora, ya que involucran cosas que escapan del contenido actual de los artículos.
Para terminar con la explicación sobre cómo se está creando el protocolo de mensajes, observa que tenemos dos valores que podrían representarse como un double o un float. Sin embargo, por los mismos motivos que se vieron en relación con el nivel de apalancamiento, necesitamos utilizar los valores literalmente. Por eso, tienen el aspecto que puedes ver en la imagen.
Pero ahora viene una pregunta que tú muy probablemente te estás haciendo: ¿por qué estos valores tienen este aspecto? ¿Qué representan, en realidad? Estos valores pueden parecer extraños porque quizá olvidas lo que hay en la línea 338 del fragmento de código. Observa que allí estamos transformando un valor financiero en un valor de puntos. Entonces, el valor 3.60 representa un valor financiero de 900 $, y el valor 3.02, un valor financiero de 755 $.
Entonces, ¿por qué no utilizar valores financieros en lugar de puntos? La razón es la sencillez. Es mucho más sencillo implementar un EA que use valores ya convertidos, que tener que convertir estos valores internamente en el EA. Tal vez esto no te resulte tan claro ahora. Pero verás que podremos hacer uso de esto de diversas formas. Pero esto quedará, de hecho, para el futuro, ya que hay cosas que necesitarán ser explicadas para que realmente entiendas la profundidad del mensaje ya ajustado dentro del EA. Pero, como dije, esto quedará para el futuro.
Conclusión
En este artículo, intenté explicar con el máximo detalle posible cómo crear un protocolo de comunicación. Este tema aún no ha terminado, ya que todavía falta por ver quién se encarga de la recepción de estos mensajes. Sin embargo, creo que se ha alcanzado el objetivo del artículo, ya que expliqué por qué debes tener cuidado al diseñar tu protocolo de comunicación si quieres usar algo diferente.
Todo esto debe planificarse ahora, porque si lo haces después, te enredarás al intentar hacer que el protocolo de comunicación logre transferir la información. Esta información será fundamental para que el EA sepa qué y cómo hacer. Así que no lo dejes para después. Estudia ahora y empieza a hacer los ajustes que consideres necesarios. En el próximo artículo, veremos la parte relacionada con el receptor, es decir, el EA.
Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/12476
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso