Desarrollo de una Startup social tecnológica, Parte I: Publicamos las Señales de MetaTrader 5 en el Twitter

laplacianlab | 26 septiembre, 2014

Introducción

En este artículo mostraremos cómo se puede vincular el terminal MetaTrader 5 con un servicio web externo poniendo el ejemplo práctico. Vamos a publicar las señales generadas por el EA en el Twitter.

Esta idea se basa en la concepción del trading automático, o así denominado el trading mediante los ordenadores. Los ordenadores del siglo XXI no poseen las facultades cognitivas pero procesan perfectamente la información y ejecutan las instrucciones. Entonces, ¿qué nos impide crear los sistemas informáticos que utilicen la inteligencia humana para tomar decisiones? Este enfoque se basa en el modelo Human-based computation (la Computación Basada en Humano, denominado a continuación como la CBH), enfocándose principalmente en el desarrollo de las herramientas del soporte para la toma de decisiones en vez de la codificación de los algoritmos de la toma de decisiones.

Al principio pensaba en crear un canal RSS con las señales comerciales generadas por mis EAs. Se trata de los sistemas de trading a medio y largo plazo, ya que esta concepción no vale para los sistemas de scalping. La persona que tiene acceso a la fuente web debe confirmar la correspondencia de las señales comerciales del robot con la situación actual del mercado, y sólo después de superar dicha prueba ellas pueden acceder al mercado en calidad de órdenes comerciales. Sin embargo, al poco tiempo he comprendido que se puede hacer todo eso de una manera más social. Me he preguntado a mí mismo: "¿Y qué me impide publicar mis señales comerciales en el Twitter?". Así, he creado mi Social Decision Support System (SDSS).

Fig. 1. Arquitectura del SDSS

Fig. 1. Arquitectura del SDSS

Además, si Usted planea arrancar una startup tecnológica relacionada con el trading en el Forex, encontrará en este artículo unas cuantas ideas que le pueden ser útiles. Puede considerarlo como un instrumento didáctico para escribir el SaaS (Software as a Service, Software como Servicio) basado en el SDSS.

Dado que el volumen del artículo es bastante grande, está dividido en dos partes para que su lectura sea más cómoda. En la primera parte nuestra atención estará centrada en la estructura del servicio web, protocolo de transmisión de datos entre el terminal Meta Trader 5 y la aplicación para Twitter, y por último en la integración de la aplicación web y el Twitter. En la segunda parte vamos a analizar la capa del diagrama MQL5 mostrada más arriba. Precisamente ella será la consumidora final del servicio web RESTful de nuestro sistema SDSS. En particular, escribiremos el código para el framework MQL5-RESTful de la misma manera como ha sido descrito en al artículo MQL5-RPC. Llamadas a Procedimientos Remotos desde MQL5: acceso a los Servicios web y análisis de los datos del Automated Trading Championship 2011.

Además, este artículo es socialmente orientado. Todos sus comentarios serán considerados a la hora de escribir la segunda parte y por eso serán acogidos con mucha satisfacción.


1. Notas para la arquitectura del SDSS

1.1. MetaTrader 5 en el servidor

Se trata del terminal MetaTrader 5 iniciado en un ordenador que funciona 24 horas al día. Este ordenador puede ser un servidor virtual privado (VPS, del inglés virtual private server), o bien un servidor dedicado (DS, del inglés dedicated server). En el servidor MetaTrader 5 se conecta con la aplicación de Twitter a través del servicio web RESTful. Para intercambiar los datos ha sido elegido el formato JSON. En la segunda parte del artículo nos centraremos en la capa MQL5 que trabaja con el servicio web de acuerdo con el protocolo de transferencia de datos que definiremos más abajo.

1.2. Aplicación de Twitter

Como ya hemos mencionado antes, en la primera parte vamos a escribir la aplicación SDSS para el Twitter. Se trata de una aplicación web PHP que recibe las señales desde el terminal MetaTrader 5, las almacena en la base de datos MySQL y las publica en la cuenta del Twitter. No obstante, se puede ampliar esta aplicación con el fin de encontrar soluciones de muchos problemas que requieren para eso las capacidades humanas.

Por ejemplo, para evaluar la fiabilidad de un Asesor Experto desde el punto de vista de una persona, lo más probable querrá recopilar la información y escribir la ontología de las señales que han sido recibidas desde «MetaTrader 5 en el servidor» y filtradas por las personas. Luego calcularemos la fiabilidad de una señal específica (tuit) basándonos en los retuits y en los marcadores correspondientes en los Favoritos. Desde luego que no se puede desarrollar esta idea en un solo artículo, pero teóricamente es posible. Se trata sólo de una aplicación basada en el modelo de Human Based Computation (HBC).

1.3. Twitter

Según la Wikipedia, el Twitter es una red social muy popular que permite llevar los microblogs, enviar y leer mensajes de texto plano de corta longitud, con un máximo de 140 caracteres, llamados tuits.



2. Especificación del servicio web RESTful

2.1. Descripción de REST

REST, SOAP y XML-RPC son tres patrones arquitecturales más usados para crear un servicio web. Puesto que en las aplicaciones Web 2.0 modernas este patrón se utiliza para el desarrollo de sus propios servicios, nosotros también vamos a escribir el código SDSS a base del REST. Sugeriría estudiar esta cuestión a fondo. El artículo The Twitter REST API ofrece una información bastante exhaustiva. En pocas palabras, la técnica REST es el intercambio de las llamadas HTTP utilizando JSON o XML como formato de intercambio de datos.

A diferencia del SOAP y XML-RPC, REST es muy fácil de implementar, y además, es más rápido. Aparte es el más sencillo ya que no requiere la especificación del protocolo a diferencia del XML-RPC y SOAP. Eso quiere decir que el desarrollador no tiene que aprender el pseudolenguaje XML para el despliegue del servicio. Por otro lado, REST puede utilizar JSON como formato de intercambio de datos entre el cliente y el servidor lo que permite minimizar el tiempo de respuesta. En efecto, cualquier objeto representado en JSON siempre ocupa menos espacio que el mismo objeto representado en XML. Eso ocurre porque JSON es más semántico, o en otros términos, JSON tiene menos elementos sintácticos que el XML para representar la información.

2.2. Ayuda de API SDSS

¿Ha leído ya el documento titulado The Twitter REST API? Tomando en cuenta todo lo arriba mencionado, la especificación de la API del Twitter puede proporcionar algunas ideas que podemos aplicar en nuestra API SDSS. Recordaré que no vamos a tratar aspectos complejos porque el presente artículo no tiene por objetivo la implementación completa del SDSS para usarlo en una startup tecnológica, sino se trata de la demostración de su aplicación práctica en la vida real donde se puede conectar el terminal MetaTrader 5 con el servicio web externo. Por lo tanto, en esta sección crearemos una API muy simple con el único método REST que utiliza la petición HTTP POST. Eso está ideado para recibir, almacenar en las bases de datos y publicar las señales del EA en la cuenta del Twitter.

2.2.1. General

La API debe alojarse en su dominio http://api.sdss-your-startup.com y estar disponible vía los protocolos HTTP o HTTPS. En las peticiones POST los parámetros deben transferirse en el formato JSON.

2.2.2. Recursos de REST

 Recursos URLDescripción
POST signal/addhttp://api.sdss-your-startup.com /signal/addTransmite la señal del EA en la aplicación del Twitter. MetaTrader 5 envía esta petición para que el SDSS guarde y publique la señal comercial en el Twitter.

Este artículo, como ya hemos dicho en la introducción, es socialmente orientado, por eso les incito a que detallen aquí los métodos REST que desean implementar en su SDSS. Dejen sus comentarios y compartan sus ideas con la comunidad MQL5.

2.2.3. POST signal/add

 ParameterDescripción
ea_id

Identificador del EA que envía nueva señal. Por ejemplo: 12345

symbol

Símbolo utilizado en esta transacción. Por ejemplo: EURUSD

opeartion

Operación a realizar. Ejemplo: BUY o SELL

value

Valor del símbolo en el momento de la transacción. Por ejemplo: 1.3214

Ejemplo de la petición:

{
    "ea_id": 1,
    "symbol": "AUDUSD",
    "operation": "BUY",
    "value": 0.9281    
}

En este ejemplo hay dos cosas importantes en las que tenemos que prestar nuestra atención. Por un lado, supongamos que tenemos sólo un terminal MetaTrader 5 que envía las señales a la aplicación Twitter. Por eso no necesitamos el identificador del terminal. Y si pasado un tiempo decidimos hacer nuestro sistema más complejo y ampliar la startup, tal vez queramos conectar varios terminales a la aplicación de Twitter.

En este caso agregaremos el campo llamado mt5_id para identificar el terminal MetaTrader 5 correspondiente. Por otro lado, cabe mencionar que la llamada descrita más arriba debe estar protegida con el mecanismo de verificación de autenticación (Basic HTTP Authentication a través de SSL, autenticación con el uso del token o OAuth). Vamos a saltar esta parte pero hay que tenerlo presente. Tenga presente que si entre el terminal MetaTrader 5 y el Twitter no hay ningún mecanismo de verificación de autenticación, cualquier persona que sepa el protocolo de transmisión de datos puede enviar una señal comercial a la aplicación de Twitter tal como se muestra en la fig. 1.


3. Diseño de la base de datos de la aplicación web

La especificación de API REST nos ha permitido ver cómo funciona el sistema, y por eso ahora podemos entender la estructura de la base de datos:

# Creación de la base de datos MySQL...

CREATE DATABASE IF NOT EXISTS sdss;

use sdss;

# Cambiar la contraseña del usuario para el proceso

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES, 
CREATE TEMPORARY TABLES ON `sdss`.* TO 'laplacianlab'@'localhost' IDENTIFIED BY 'password'; 

CREATE TABLE IF NOT EXISTS eas (
    id mediumint UNSIGNED NOT NULL AUTO_INCREMENT, 
    name VARCHAR(32),
    description TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS signals (
    id int UNSIGNED NOT NULL AUTO_INCREMENT,
    id_ea mediumint UNSIGNED NOT NULL,
    symbol VARCHAR(10) NOT NULL,
    operation VARCHAR(6) NOT NULL,
    value DECIMAL(9,5) NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    FOREIGN KEY (id_ea) REFERENCES eas(id)
) ENGINE=InnoDB;

# Enviar datos de ejemplos...

INSERT INTO eas(name, description) VALUES
('Bollinger Bands', '<p>Robot basado en las Bandas de Bollinger. Trabaja con los gráficos H4.</p>'),
('Two EMA', '<p>Robot basado en la intersección de dos Medias Móviles. Trabaja con los gráficos H4.</p>');

4. Programación de los servicios web RESTful con PHP

Según afirman los desorralladores, Slim es un microframework con PHP que permite escribir rápido las aplicaciones web y API simples pero potentes. ¡Pues sí, lo han entendido bien! Queremos escribir nuestra API RESTful con Slim utilizando muy pocas líneas del código. Recordaré que por razones de sencillez y claridad vamos a escribir el código sólo para un método HTTP POST. Las particularidades de trabajo con Slim se puede encontrar en la documentación oficial.

Figura 2. Estructura de catálogos PHP API basada en Slim

Fig. 2. Estructura de catálogos PHP API basada en Slim

config\config.php

// Creación de constantes.

// Generales

define('BASE_URL', 'laplacianlab.local');
define('APPLICATION_PATH', realpath(dirname(__FILE__)) . '/../');

// Conexión a la base de datos

define('DB_NAME', 'sdss');
define('DB_USER', 'laplacianlab');
define('DB_PASSWORD', 'password'); // ¡No olvide cambiar la contraseña en el servidor de trabajo!
define('DB_SERVER', 'localhost');

model\DBConnection.php

class DBConnection 
{ 
    private static $instance; 
    private $mysqli;
 
    private function __construct()
    { 
        $this->mysqli = new MySQLI(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME); 
    } 
 
    public static function getInstance()
    {
        if (!self::$instance instanceof self) self::$instance = new self; 
        return self::$instance;
    } 
 
    public function getHandler()
    { 
        return $this->mysqli; 
    } 
}

public\.htaccess

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes...
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

public\index.php

// Lógica de autoarranque

require_once '../config/config.php';

set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . '/vendor/');
set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . '/model/');

require_once 'slim/slim/Slim/Slim.php';
require_once 'DBConnection.php';

use \Slim\Slim;

Slim::registerAutoloader();

$app = new Slim();
$app->response->headers->set('Content-Type', 'application/json');

// RESTful API methods

// POST signal/add

$app->post('/signal/add', function() {   
    $request =  Slim::getInstance()->request();    
    $signal = json_decode($request->getBody());
    $sql = 'INSERT INTO signals(id_ea, symbol, operation, value) VALUES (' 
            . mysql_real_escape_string($signal->ea_id) . ",'"
            . mysql_real_escape_string($signal->symbol) . "','"
            . mysql_real_escape_string($signal->operation) . "',"
            . mysql_real_escape_string($signal->value) . ')';  
    DBConnection::getInstance()->getHandler()->query($sql);
    $signal->id = DBConnection::getInstance()->getHandler()->insert_id;
    echo json_encode($signal);        
});

// ¡Más métodos API!.., de acuerdo con la especificación API

$app->run();

composer.json

{
    "require": {
        "slim/slim": "2.*",
        "abraham/twitteroauth": "dev-master"
    }
}

Con todo eso podemos hacer la prueba del servicio web en nuestro ordenador local. Por cierto, no olviden (1) añadir nueva entrada en el archivo hosts para que Windows pueda convertir el nombre del dominio local api.laplacianlab.local, y (2) crear el anfitrión virtual para Apache.

C:\Windows\System32\Drivers\etc\hosts

::1 localhost
# Copyright (c) 1993-2009 Microsoft Corp.
#
# Es el ejemplo del archivo HOSTS utilizado por Microsoft TCP/IP para Windows.
#
# Este archivo contiene la comparación de las direcciones IP y los host names. Cada 
# entrada debe ocupar una línea separada. La dirección IP
# debe colocarse en la primera columna la que sigue el host name correspondiente.
# La dirección IP debe separarse por lo menos con un 
# espacio.
#
# Además, los comentarios (como éste) pueden ser añadidos en las líneas
# separadas o a continuación del nombre del equipo marcado con el signo '#'.
#
# Por ejemplo:
#
#      102.54.94.97     rhino.acme.com          # servidor fuente
#       38.25.63.10     x.acme.com              # x host cliente

# La conversión del nombre del host local debe realizarse en  DNS.
#       127.0.0.1       host local
#       ::1             host local

127.0.0.1       host local
127.0.0.1       api.laplacianlab.local

httpd-vhosts.conf

# Anfitriones virtuales
#
# Required modules: mod_log_config

# Si desea mantener varios dominios/hosts en su
# ordenador, puede instalar para ellos los contenedores VirtualHost. La mayoría de las configuraciones
# utilizan los anfitriones virtuales con el acceso por el nombre lo que permite al servidor no preocuparse por 
# las direcciones IP. Eso se indica con asteriscos en las directivas más abajo.
#
# Para ver la documentación, siga el enlace 
# <URL:http://httpd.apache.org/docs/2.4/vhosts/>
# para leer la descripción completa de la instalación del anfitrión virtual.
#
# Para comprobar la configuración de su anfitrión virtual,
# utilice el parámetro de la línea de comandos '-S'.

#
# Ejemplo de VirtualHost:
# Casi cualquier directiva de Apache puede ir al contenedor VirtualHost.
# La primera sección de VirtualHost sirve para todas las peticiones que
# no coinciden con ServerName o ServerAlias en cualquiera de los bloques <VirtualHost>.
#
<VirtualHost *:80>
        ServerAdmin webmaster@laplacianlab.local
        DocumentRoot "c:/wamp/www/laplacianlab/public"
        ServerName api.laplacianlab.local
        ErrorLog "logs/api.laplacianlab.local-error.log"
        CustomLog "logs/api.laplacianlab.local-access.log" common
        <directory "c:/wamp/www/laplacianlab/public">
                Options FollowSymLinks
                AllowOverride all
                Order Deny,Allow
                Deny from all
                Allow from 127.0.0.1
        </directory>    
</VirtualHost>
Ahora vamos a probar nuestro primer recurso REST usando el RESTClient que sirve de complemento para Firefox para depurar los servicios web RESTful. Si todo sale bien, el servicio web tiene que iniciar la lógica que hemos codificado a través del método Slim y enviarnos el resultado HTTP 200 en la respuesta de JSON.


Figura 3. Enviamos la petición POST signal/add a http://api.laplacianlab.local

Fig. 3. Enviamos la petición POST signal/add a http://api.laplacianlab.local

La cabecera de la respuesta HTTP a la petición POST signal/add:

Status Code: 200 OK
Connection: Keep-Alive
Content-Length: 70
Content-Type: application/json
Date: Mon, 07 Apr 2014 18:12:34 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.4 (Win64) PHP/5.4.12
X-Powered-By: PHP/5.4.12

Es el cuerpo de la respuesta HTTP:

{
        "ea_id": 1,
        "symbol": "AUDUSD",
        "operation": "BUY",
        "value": 0.9281,
        "id": 22
}

¡Todo ha salido perfectamente! Hemos implementado la parte de nuestro SDSS que corresponde a la imagen de abajo.¡Pero recuerden que en el escenario real tiene que haber una capa de autenticación para garantizar la protección de las llamadas de este tipo!

Figura 6. MetaTrader 5 y la aplicación Twitter interactuan mediante el servicio web RESTful

Fig. 4. MetaTrader 5 y la aplicación Twitter interactuan mediante el servicio web RESTful


5. Integración de la aplicación web con el Twitter

Ahora pasaremos a la parte del diagrama de la red que se ocupa de tuitear las señales comerciales desde la aplicación Slim PHP Twitter en el Twitter.

Figura 5. Publicación en el Twitter de las señales comerciales desde la aplicación de Twitter

Fig. 5. Publicación en el Twitter de las señales comerciales desde la aplicación de Twitter

¿Y ahora qué hacemos? ¡Ha vuelto a acertar! Primeramente, va a necesitar una aplicación Twitter. Para eso entre, por favor, en la página Twitter Developers utilizando los datos de su cuenta en Twitter (por lo tanto, necesitará una cuenta de Twitter para poder crear una aplicación Twitter). Luego entre en "My Applications" y haga clic en "Create New App".


Figura 6. Creamos nueva aplicación en la página Twitter Developers

Fig. 6. Creamos nueva aplicación en la página Twitter Developers

Necesitará introducir los detalles de su nueva aplicación y aceptar Developer Rules of the Road. Aquí tienen el ejemplo de mi aplicación:

Name: Laplacianlab's SDSS

Description: Social Decision Support System

Website: http://api.laplacianlab.local

Callback URL: http://api.laplacianlab.local/twitter/oauth_callback

Ahora busque la pestaña "Permissions" y actualice los permisos hasta "Read and Write". Y por último, después de crear la aplicación Twitter, apunte su clave API, su API secret y el retrollamado Oauth para utilizarlos como constantes en el archivo config\config.php:

// Twitter OAuth

define('API_KEY', 'akMnfXR45MkoaWbZoPiu3');
define('API_SECRET', '45Mkoa54NcvQRBbf119qWerty0DnIW45MncvFgqw');
define('OAUTH_CALLBACK', 'http://api.laplacianlab.local/twitter/oauth_callback');

En este paso estamos conectando la aplicación web Slim PHP micro con Laplacianlab's SDSS (la aplicación Twitter que hemos creado antes). Para hacerlo, hace falta poseer conocimientos básicos del protocolo the OAuth 2.0. Puede encontrar los elementos de este protocolo en la documentación oficial. Tendrá que estar familiarizado con el diagrama OAuth.

Fig 7. Diagrama OAuth

Fig. 7. Diagrama OAuth

Pues bien, de acuerdo con este diagrama ahora tendremos que crear la tabla MySQL en la que guardaremos los datos de las fuentes (los tuiteros que quieren tuitear las señales comerciales):

CREATE TABLE IF NOT EXISTS twitterers (
        id mediumint UNSIGNED NOT NULL AUTO_INCREMENT, 
        twitter_id VARCHAR(255),
        access_token TEXT,
        access_token_secret TEXT,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id)
) ENGINE=InnoDB;

En particular, estamos usando TwitterOAuth que es una librería PHP para trabajar con OAuth API Twitter. Si ha instalado Slim a través de Composer utilizando el archivo composer.json que he adjuntado en la sección anterior, no necesita preocuparse por la instalación de esta librería porque TwitterOAuth ya estará copiada a la carpeta del proveedor de la aplicación PHP.

De lo contrario, podrá bajar este componente PHP de la página GitHub en cualquier momento. Disponiendo de OAuth flow, sólo nos queda programar el método de aplicación de los permisos en Laplacianlab's SDSS y el retrollamado oauth. Por ahora nuestro SDSS es tan simple que podemos escribir todo en el archivo index.php.

public\index.php

// Lógica de autoarranque

require_once '../config/config.php';

set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . '/vendor/');
set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . '/model/');

require_once 'slim/slim/Slim/Slim.php';
require_once 'abraham/twitteroauth/twitteroauth/twitteroauth.php';
require_once 'DBConnection.php';

use \Slim\Slim;

session_start();

Slim::registerAutoloader();

$app = new Slim();
$app->response->headers->set('Content-Type', 'application/json');

// RESTful API methods

// POST signal/add

$app->post('/signal/add', function() {   
    $request =  Slim::getInstance()->request();    
    $signal = json_decode($request->getBody());
    $sql = 'INSERT INTO signals(id_ea, symbol, operation, value) VALUES (' 
            . mysql_real_escape_string($signal->ea_id) . ",'"
            . mysql_real_escape_string($signal->symbol) . "','"
            . mysql_real_escape_string($signal->operation) . "',"
            . mysql_real_escape_string($signal->value) . ')';
    DBConnection::getInstance()->getHandler()->query($sql);
    $signal->id = DBConnection::getInstance()->getHandler()->insert_id;
    echo json_encode($signal);
});

// ¡Aquí van a haber otros métodos API!.., de acuerdo con la especificación API

// Twitter OAuth flow

// Este método se utiliza por los usuarios para permitir al Laplacianlab's SDSS publicar las señales en el Twitter 
// en nombre de ellos.

$app->get('/tweet-signals', function() use ($app) {   
    if (empty($_SESSION['twitter']['access_token']) || empty($_SESSION['twitter']['access_token_secret']))
    {
        $connection = new TwitterOAuth(API_KEY, API_SECRET);
        $request_token = $connection->getRequestToken(OAUTH_CALLBACK);
        if ($request_token)
        {
            $_SESSION['twitter'] = array(
                'request_token' => $request_token['oauth_token'],
                'request_token_secret' => $request_token['oauth_token_secret']
            );
            switch ($connection->http_code) 
            {
                case 200:
                    $url = $connection->getAuthorizeURL($request_token['oauth_token']);                    
                    // redirect to Twitter
                    $app->redirect($url);
                    break;
                default:
                    echo '{"error":{"text":"Connection with Twitter failed"}}';
                break;
            }
        }
        else 
        {
            echo '{"error":{"text":"Error Receiving Request Token"}}';
        }
    } 
    else 
    {    
        echo '{"message":{"text":"Everything is ok! Laplacianlab\'s SDSS '
        . 'puede publicar en el Twitter las señales comerciales en nombre de Usted. Por favor, si no '
        . 'desea que el SDSS publique en el Twitter las señales en nombre de Usted, entre en su cuenta del Twitter '
        . 'y revoque el acceso."}}';
    }    
});

// Es OAuth callback

$app->get('/twitter/oauth_callback', function() use ($app) {   
    if(isset($_GET['oauth_token']))
    {
        $connection = new TwitterOAuth(
            API_KEY, 
            API_SECRET, 
            $_SESSION['twitter']['request_token'], 
            $_SESSION['twitter']['request_token_secret']);
        $access_token = $connection->getAccessToken($_REQUEST['oauth_verifier']);
        if($access_token)
        {       
            $connection = new TwitterOAuth(
                API_KEY, 
                API_SECRET, 
                $access_token['oauth_token'], 
                $access_token['oauth_token_secret']);
            // Instalamos Twitter API versión 1.1.
            $connection->host = "https://api.twitter.com/1.1/";
            $params = array('include_entities' => 'false');
            $content = $connection->get('account/verify_credentials', $params);            
            if($content && isset($content->screen_name) && isset($content->name))
            {
                $_SESSION['twitter'] = array(
                    'id' => $content->id,
                    'access_token' => $access_token['oauth_token'],
                    'access_token_secret' => $access_token['oauth_token_secret']
                );               
                // quitamos de la sesión el token de la petición
                unset($_SESSION['twitter']['request_token']);
                unset($_SESSION['twitter']['request_token_secret']); 
                // Los tokens de acceso OAuth del Twitter son permanentes hasta que estén anulados, y
                // nosotros intentaremos actualizarlos cuando el tuitero trate de conceder el acceso
                // permiso repetido
                $sql = "SELECT * FROM twitterers WHERE twitter_id='$content->id'";
                $result = DBConnection::getInstance()->getHandler()->query($sql);
                if($result->num_rows)
                {
                    $sql = "UPDATE twitterers SET "
                    . "access_token = '" . mysql_real_escape_string($access_token['oauth_token']) . "', "
                    . "access_token_secret = '" . mysql_real_escape_string($access_token['oauth_token_secret']) . "' "
                    . "WHERE twitter_id ='" . $content->id . "'";
                }
                else
                {
                    $sql = "INSERT INTO twitterers(twitter_id, access_token, access_token_secret) "
                    . "VALUES ('"
                    . mysql_real_escape_string($content->id) . "','"
                    . mysql_real_escape_string($access_token['oauth_token']) . "','"
                    . mysql_real_escape_string($access_token['oauth_token_secret']) . "')";
                }                
                DBConnection::getInstance()->getHandler()->query($sql);
                echo '{"message":{"text":"Everything is ok! Laplacianlab\'s SDSS '
                . 'ahora podemos publicar en el Twitter las señales comerciales en nombre de Usted. Si no desea que '
                . 'el SDSS siga publicando en el Twitter las señales en nombre de Usted, entre en su cuenta del Twitter '
                . 'y revoque el acceso."}}';
            }
            else
            {
                echo '{"error":{"text":"Login error"}}';
            }
        }
    } 
    else
    { 
        echo '{"error":{"text":"Login error"}}';
    }
});

$app->run();

 

Lo más importante aquí es almacenar en las bases de datos dos fragmentos de información que permite al SDSS hacer las llamadas autorizadas al Twitter en nombre de los usuarios con derecho de acceso. Estos dos fragmentos de información (el token de acceso y el secreto del token de acceso) se mantienen permanentes hasta que el usuario los anule. De este modo, el SDSS nunca guarda las credenciales del usuario. Por otra parte, los usuarios pueden eliminar el permiso de acceso durante el proceso de anulación.

Mientras el SDSS basada en PHP tenga el token de acceso correcto y el secreto del token de acceso, puede hacer las llamadas Twitter como se muestra a continuación:

// Supongamos que un objeto con el nombre $user ha accedido a los tokens...

$connection = new TwitterOAuth(
    API_KEY, 
    API_SECRET, 
    $user->getAccessToken(), 
    $user->getAccessTokenSecret());       

$message = "Hello world! Soy Laplacianlab's SDSS y estoy tuiteando en nombre del tuitero.";

$connection->post('statuses/update', array('status' => $message));

Tenemos todo lo que necesitamos. Ahora terminar el recurso POST signal/add de la API del SDSS es muy fácil. Hemos empezado a escribir el código para él en la sección 4. Programación de los servicios web RESTful con PHP. Pueden ejercitarse en adición del código PHP para la publicación de prueba en el Twitter.


Conclusión

En este artículo hemos visto cómo se puede conectar el terminal MetaTrader 5 con el Twitter para poder publicar las señales comerciales del Asesor Experto. Hemos desarrollado el sistema a base del ordenador que reúne en sí los recursos computacioneles de los robots y las capacidades para el discernimiento de las personas. Queremos que las señales generadas por el robot se sometan a una prueba adicional realizada por las personas antes de que vayan a ser envidas al mercado como las órdenes del trading. Pues, esta idea nos ha ayudado descubrir un tema nuevo y tan apasionante que acumula los conocimientos sobre los sistemas del trading automatizado, cuando los usuarios publican las señales de los demás en su página o las añaden a los Favoritos. Es una aplicación práctica a base del paradigma de Human-based computation (HBC).

La implantación de un Social Decision Support System completado requiere demasiado tiempo, por esta razón el presente ejercicio puede servir de una idea para lanzar una startup tecnológica. Hemos empezado a crear un SDSS que se compone de tres partes principales:

  1. Terminal MetaTrader 5 que trabaja a base de un servidor virtual privado o un servidor dedicado;
  2. Aplicación web Twitter PHP a base de Slim;
  3. Twitter;

En particular, hemos creado en esta parte la arquitectura del servicio web RESTful que permite a MetaTrader 5 interactuar con la aplicación Slim PHP. Además, hemos conectado la aplicación web PHP con el Twitter vía el protocolo OAuth. En la siguiente parte escribiremos el código para el framework MQL5-RESTful de la misma manera como ha sido descrito en al artículo MQL5-RPC. Llamadas a Procedimientos Remotos desde MQL5: acceso a los Servicios web y análisis de los datos del Automated Trading Championship 2011.