MT5信号接入Twitter实战
🐦

MT5信号接入Twitter实战

用REST与OAuth搭建社交决策支持系统

交易策略 难度 · 进阶 2026-07-01 7 分钟阅读
#MT5#信号发布#REST#Twitter

什么是社交决策支持系统(SDSS)

传统自动交易系统依赖EA独立决策并直接下单,但计算机缺乏认知能力,在复杂市况下可能失效。社交决策支持系统(SDSS)基于以人为本的计算(HBC)模式,将MT5终端的EA信号作为数据输出,交由人类专家过滤验证后再决定是否执行。本文以将信号发布到Twitter为例,构建一个轻量SDSS:EA信号经Web服务存储并推文,关注者可作为人工过滤器。

SDSS并非完整商业产品,而是一种技术创新思路。它证明MT5不仅能做本地交易,还能作为信息源与外部社交网络打通,为后续分析信号可靠性、建立知识本体提供基础。对于中线或长线系统,这种人工+自动的混合模式比纯剥头皮自动化更有实用价值。

✦ 适用场景
SDSS特别适合不愿完全托管给EA、希望保留人工确认环节的策略作者;对短周期剥头皮系统意义不大,因为信号时延会抵消优势。

SDSS整体架构与组件分工

系统由三部分组成:运行在VPS或专用服务器上的MetaTrader 5终端,负责24小时运行EA并准备信号;基于Slim微框架的PHP Web应用,接收JSON信号、存MySQL、调用Twitter API;以及Twitter本身作为社交发布渠道。MT5与PHP应用之间采用RESTful通信,数据格式为JSON,第二部分才会用MQL5的WebRequest实现客户端。

在架构设计中,若仅有一台终端发送信号,可省略终端ID;若扩展多终端,需增加mt5_id字段区分来源。无论规模大小,MT5与Web应用间必须加入认证机制(如Basic Auth+SSL或OAuth),否则通信协议暴露会导致任何人都能伪造信号。

为什么选择REST而非SOAP或XML-RPC

REST、SOAP、XML-RPC是三种主流Web服务范式。SOAP和XML-RPC依赖繁重的XML协议规范,开发者需掌握大量伪语言细节;REST仅利用HTTP原生方法,配合JSON数据,实现极简且响应更快。JSON语义密度高,描述同对象字节数少于XML,降低带宽与解析开销,非常适合MT5这类轻量客户端调用。

Twitter官方API即采用REST风格,本文直接借鉴其设计理念。我们只需一个POST方法接收信号,不必构建完整CRUD,降低学习曲线。但需注意,REST的松散规范意味着安全层要自行补齐,不能依赖协议本身保障。

⚠ 安全提醒
示例代码中未含认证,生产环境务必加上HTTPS与令牌校验,否则信号接口会被滥用。

SDSS API规范与信号数据格式

API根地址为http://api.sdss-your-startup.com,通过POST提交JSON实体。核心资源为/signal/add,参数包含ea_id(EA标识)、symbol(品种如EURUSD)、operation(BUY/SELL)、value(价位)。下方为请求体示例,MT5后续篇将构造相同结构发送。

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

该设计假设单终端场景,若多终端并发,应扩展mt5_id。参数经JSON解码后由PHP写入signals表,并返回带自增id的相同对象确认接收。这种极简契约方便任何客户端对接,也易于调试。

数据库设计与MySQL建表脚本

为支持信号存储与EA管理,需建立sdss库。eas表记录EA元数据,signals表以外键关联EA,并保存品种、方向、价位与时间。下方SQL包含授权用户与示例数据,生产请修改密码。此结构可支撑基础SDSS运作,后续可加twitterers表存授权。

# MySQL database creation...

CREATE DATABASE IF NOT EXISTS sdss;

use sdss;

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;

INSERT INTO eas(name, description) VALUES
('Bollinger Bands', '<p>Robot based on Bollinger Bands. Works with H4 charts.</p>'),
('Two EMA', '<p>Robot based on the crossing of two MA. Works with H4 charts.</p>');

建表时采用InnoDB引擎以支持外键。signals.value用DECIMAL(9,5)精确存储汇率,避免浮点误差。实际部署中应为laplacianlab用户设强密码,并限制IP访问。

基于Slim的PHP RESTful服务实现

Slim是PHP微框架,能用极少代码暴露API。项目结构含config、model、public入口。config.php定义库名、用户等常量;DBConnection类用单例封装mysqli;.htaccess重写路由至index.php;入口文件注册Slim并声明/post('/signal/add')。下方展示核心常量与单例。

<?php
// Creating constants.
define('BASE_URL', 'laplacianlab.local');
define('APPLICATION_PATH', realpath(dirname(__FILE__)) . '/../');
define('DB_NAME', 'sdss');
define('DB_USER', 'laplacianlab');
define('DB_PASSWORD', 'password');
define('DB_SERVER', 'localhost');
<?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; } 
}

入口脚本引入Slim与DB类,设置响应头为JSON,在闭包中解码请求体并拼SQL插入。注意示例用mysql_real_escape_string防注入,现代环境应改用mysqli预处理。返回json_encode($signal)含新id,便于客户端确认。

<?php
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');
$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);        
});
$app->run();

本地测试需改hosts添加127.0.0.1 api.laplacianlab.local,并在Apache建虚拟主机指到public目录。用Firefox RESTClient发POST,正常返回HTTP 200及JSON。下图响应头证明服务可用。

Status Code: 200 OK
Connection: Keep-Alive
Content-Length: 70
Content-Type: application/json
Date: Mon, 07 Apr 2014 18:12:34 GMT
Server: Apache/2.4.4 (Win64) PHP/5.4.12
X-Powered-By: PHP/5.4.12
{
        "ea_id": 1,
        "symbol": "AUDUSD",
        "operation": "BUY",
        "value": 0.9281,
        "id": 22
}

Twitter应用创建与OAuth集成

要在Twitter发信号,先于developer网站建应用,填名称、描述、网站、回调URL,权限设为读和写。记下API_KEY、API_SECRET、OAUTH_CALLBACK写入config。OAuth 2.0流程中,用户访问/tweet-signals时跳转Twitter授权,回调存access_token与secret于twitterers表,之后PHP可代发。

define('API_KEY', 'akMnfXR45MkoaWbZoPiu3');
define('API_SECRET', '45Mkoa54NcvQRBbf119qWerty0DnIW45MncvFgqw');
define('OAUTH_CALLBACK', 'http://api.laplacianlab.local/twitter/oauth_callback');
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;

用TwitterOAuth库简化调用。composer.json需含slim与abraham/twitteroauth。授权后,用$connection->post('statuses/update', array('status'=>$msg))发推。SDSS永不存用户密码,仅持令牌,用户可随时撤权。

// Let's assume there's an object named $user to access the tokens...
$connection = new TwitterOAuth(
    API_KEY, 
    API_SECRET, 
    $user->getAccessToken(), 
    $user->getAccessTokenSecret());       
$message = "Hello world! I am Laplacianlab's SDSS and I am tweeting on behalf of a tweeterer.";
$connection->post('statuses/update', array('status' => $message));
✦ 调试建议
先以命令行PHP测试OAuth回调节点,确认令牌写入库后再接信号流,避免反复跳转。

常见坑与对比总结

实践中易错点:hosts与虚拟主机未配导致本地域名无法解析;Slim旧版路由大小写敏感;mysql_*函数已废弃应迁移mysqli;OAuth回调URL须与Twitter后台完全一致含http。相比直接MT5信号服务,自建SDSS灵活但需维护基建;适合个性化社交分发而非跟单托管。

本文第一部分打通了MT5→Web→Twitter通路,第二部分将用MQL5 WebRequest补全终端侧客户端。读者可延伸加人工验证队列、信号评分等HBC应用。参考原文:https://www.mql5.com/zh/articles/925

常见问题

先在VPS运行MT5,用PHP Slim写/signal/add接收JSON信号存MySQL,通过TwitterOAuth代发推文;MT5侧下篇用WebRequest POST相同JSON即可,详见https://www.mql5.com/zh/articles/925
POST /signal/add需ea_id、symbol、operation(BUY/SELL)、value四个字段,JSON格式,单终端可省略mt5_id,返回带id的同一对象表示成功。
在Windows hosts加127.0.0.1 api.laplacianlab.local,Apache建VirtualHost指到public目录,用RESTClient发POST验证200响应。
Twitter禁止明文密码,需建应用获API_KEY,引导用户授权拿access_token存库,PHP用TwitterOAuth库代发,用户可随时撤权。
示例无认证,生产必须加HTTPS与令牌校验,否则协议暴露会被伪造信号;多终端应扩展mt5_id区分来源。