zeltsnet/metatrader5-laravel

An opinionated meta trader 5 SDK built on top of zeltsnet/metatrader5, supercharged for Laravel.

v0.1.0-beta 2024-05-17 06:58 UTC

This package is auto-updated.

Last update: 2024-05-21 17:25:46 UTC


README

An opinionated meta trader 5 SDK built on top of zeltsnet/metatrader5, supercharged for Laravel.

Installation

You can install the package via composer:

composer require zeltsnet/metatrader5-laravel

Usage

This package offers some Laravel-specific functionality that will make things easier for you.

Prerequisites

We like dependency injection, and we recommend binding the concrete MetaTraderGateway implementation to the container. We left that part to you since you might resolve a server in different ways: e.g: from config, from DB, etc... In case you're using one server, can configure it in the metatrader5.php configuration file. We'll use that as an example in this guide.

Note

Meta Trader 5 Web API requires you to keep the connection alive, and perform pings. That said, and based on your use case, there are multiple ways to do so. We'll cover two cases: in a queue worker and in Laravel Octane, but before we proceed, you will need to create that instance.

In your service provider, create a Server instance. Then, create a concrete instance that you want to bind.

use Zeltsnet\MetaTrader5\Core\Contracts\MetaTraderGateway;
use Zeltsnet\MetaTrader5\Core\DefaultGateway;
use Zeltsnet\MetaTrader5\Core\ValueObjects\Server;

public function register(): void
{
    // Create a Server object with the necessary credentials.
    $server = new Server(
        host: config('metatrader5.server.host'),
        port: config('metatrader5.server.port'),
        version: config('metatrader5.server.version'),
        login: config('metatrader5.server.login'),
        password: config('metatrader5.server.password'),
        ping_interval: config('metatrader5.server.ping_interval'),
        accountType: config('metatrader5.account-type'),
        webAgent: config('metatrader5.web-agent'),
        passwordHashExtra: config('metatrader5.password-hash-extra'),
    );
        
    // Create the gateway instance.
    $metaTraderGateway = new DefaultGateway($server);
    
    // Create the singleton.
    $this->app->singleton(MetaTraderGateway::class, fn() => $metaTraderGateway);
}

Queue Worker

If you want to run this inside a queue worker, make sure to only bind it if the app is running in console. Also, to avoid making an instance in artisan commands, we suggest having another ENV variable that will be set to true for queue workers.

use Zeltsnet\MetaTrader5\Core\Contracts\MetaTraderGateway;
use Zeltsnet\MetaTrader5\Core\DefaultGateway;
// ...
public function register(): void
{
    if (! $this->app->runningInConsole()) {
        return;
    }

    if (! config('metatrader5.enabled')) {
        return;
    }
    
    // Create the gateway instance.
    $metaTraderGateway = new DefaultGateway(new Server(...));
    
    // We will also connect so that the connection is established as soon as the queue worker is up.
    $metaTraderGateway->connect();
    
    // Create the singleton.
    $this->app->singleton(MetaTraderGateway::class, fn() => $metaTraderGateway);
}

Additionally, we need to keep the connection alive by sending ping requests every 20 seconds.

use Zeltsnet\MetaTrader5\Core\Contracts\MetaTraderGateway;
// ...
public function boot(): void
{
    if (! $this->app->runningInConsole()) {
        return;
    }
    
    if (! config('metatrader5.enabled')) {
        return;
    }
    
    /** @var MetaTraderGateway $metaTrader */
    $metaTrader = $this->app->make(MetaTraderGateway::class);
    Queue::looping(function () use ($metaTrader) {
        if (! $metaTrader->shouldPing()) {
            return;
        }
        $metaTrader->ping();
    });
}

Laravel Octane

If you're using Laravel Octane, you have the possibility to store the instance in memory. Incoming HTTP requests, that need to call the Meta Trader 5 Web API can use the instance that's in memory that has a connection that's alive.

To do so, we have provided the following event listeners that can be added to your octane.php listeners section.

    // Create a new instance when the worker starts
    WorkerStarting::class => [
        Zeltsnet\MetaTrader5Laravel\Listeners\ConnectToMetaTraderServer::class    
    ],
    
    // Ping on every incoming request or connect if the connection died
    RequestReceived::class => [
        Zeltsnet\MetaTrader5Laravel\Listeners\PingMetaTraderServer::class,
    ],

    // Close connection when worker is stopped
    WorkerStopping::class => [
        Zeltsnet\MetaTrader5Laravel\Listeners\DisconnectFromMetaTraderServer::class,
    ]

Tip

Notice how we're only pinging when the request is received. If you're using Swoole, you can benefit from intervals to ping every 20 seconds.

Middleware

Finally, we have included a middleware that pings the connection, just in case you need to ping a connection for specific HTTP requests.

Route::get(...)->middleware([\Zeltsnet\MetaTrader5Laravel\Middleware\PingMetaTrader::class]);

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please use the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.