PHP code example of oyi77 / metaapi-cloud-php-sdk
1. Go to this page and download the library: Download oyi77/metaapi-cloud-php-sdk library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
oyi77 / metaapi-cloud-php-sdk example snippets
use Oyi77\MetaapiCloudPhpSdk\MetaApi\MetaApi;
$token = 'AUTH_TOKEN';
$accountId = 'ACCOUNT_ID';
$metaApi = new MetaApi($token, ['region' => 'new-york']);
// RPC connection for query-and-response workflows
$rpc = $metaApi->rpcConnection($accountId);
$rpc->connect();
$rpc->waitSynchronized();
// Query terminal state
$accountInfo = $rpc->getAccountInformation();
$positions = $rpc->getPositions();
$symbols = $rpc->getSymbols();
$serverTime = $rpc->getServerTime();
// Calculate margin
$marginInfo = $rpc->calculateMargin([
'symbol' => 'GBPUSD',
'type' => 'ORDER_TYPE_BUY',
'volume' => 0.1,
'openPrice' => 1.25,
]);
// Execute trades with convenience methods
$result = $rpc->createMarketBuyOrder('EURUSD', 0.01, 1.0900, 1.1100, [
'comment' => 'Trade from PHP',
'clientId' => 'php_' . time(),
'trailingStopLoss' => [
'distance' => ['distance' => 50, 'units' => 'RELATIVE_POINTS'],
],
]);
$rpc->close();
use Oyi77\MetaapiCloudPhpSdk\MetaApi\MetaApi;
use Oyi77\MetaapiCloudPhpSdk\MetaApi\Streaming\SynchronizationListener;
// Streaming connection for real-time updates
$stream = $metaApi->streamingConnection($accountId);
// Add typed listener for market data events
class MyListener implements SynchronizationListener {
public function onSymbolPriceUpdated(int $instanceIndex, array $price): void {
echo "Price update: {$price['symbol']} bid={$price['bid']} ask={$price['ask']}\n";
}
public function onCandlesUpdated(int $instanceIndex, array $candles, ?float $equity = null, ?float $margin = null, ?float $freeMargin = null, ?float $marginLevel = null): void {
// Handle candle updates
}
// Implement other methods as needed (ticks, books, positions, orders, etc.)
public function onTicksUpdated(...$args): void {}
public function onBooksUpdated(...$args): void {}
public function onSubscriptionDowngraded(...$args): void {}
public function onPositionsUpdated(...$args): void {}
public function onOrdersUpdated(...$args): void {}
public function onHistoryOrdersUpdated(...$args): void {}
public function onDealsUpdated(...$args): void {}
}
$stream->addTypedSynchronizationListener(new MyListener());
$stream->connect();
$stream->waitSynchronized();
// Subscribe to market data
$stream->subscribeToMarketData('EURUSD', [
['type' => 'quotes', 'intervalInMilliseconds' => 5000],
['type' => 'candles', 'timeframe' => '1m'],
['type' => 'ticks'],
]);
// Access cached terminal state
$price = $stream->terminalState->price('EURUSD');
$spec = $stream->terminalState->specification('EURUSD');
$accountInfo = $stream->terminalState->accountInformation;
$positions = $stream->terminalState->positions;
// Access history storage
$historyOrders = $stream->historyStorage->getHistoryOrders();
$deals = $stream->historyStorage->getDeals();
// Poll for events
while (true) {
$stream->poll(0.25);
}
$stream->close();
use Oyi77\MetaapiCloudPhpSdk\AccountApi;
$account = new AccountApi('AUTH_TOKEN');
when statusCode >= 200 && statusCode < 300;
try {
return $account->create([
"login" => "123456",
"password" => "password",
"name" => "testAccount",
"server" => "ICMarketsSC-Demo",
"platform" => "mt5",
"magic" => 123456
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
[
"id" => "1eda642a-a9a3-457c-99af-3bc5e8d5c4c9",
"state" => "DEPLOYED"
]
try {
return $account->readById("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Using the legacy method (deprecated)
return $account->readAll();
// Using infinite scroll pagination (recommended)
return $account->readAllWithInfiniteScroll([
'limit' => 10,
'offset' => 0,
'query' => 'ICMarketsSC-MT5',
'state' => ['DEPLOYED']
]);
// Using classic pagination (returns count for page calculation)
$result = $account->readAllWithClassicPagination([
'limit' => 10,
'offset' => 0
]);
// $result['items'] contains accounts
// $result['count'] contains total count
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $account->update("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9",[
"password" => "password",
"name" => "testAccount",
"server" => "ICMarketsSC-Demo",
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $account->unDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
// you can pass other parameters
return $account->unDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $account->deploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
// you can pass other parameters
return $account->deploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $account->reDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
// you can pass other parameters
return $account->reDeploy("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", false);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $account->delete("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9");
// you can pass other parameters
return $account->delete("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", true);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Create a link that allows end users to configure their account
$link = $account->createConfigurationLink("1eda642a-a9a3-457c-99af-3bc5e8d5c4c9", 7); // 7 days validity
// Use $link['url'] to redirect users to account configuration page
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\CopyFactory;
$copyfactory = new CopyFactory('AUTH_TOKEN');
try {
return $copyfactory->generateStrategyId();
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Using legacy method (deprecated)
return $copyfactory->strategies();
// Using infinite scroll pagination (recommended)
return $copyfactory->strategiesWithInfiniteScroll([
' 'offset' => 0
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->strategy("strategid");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->updateStrategy("strategid", [
"name" => "Test strategy",
"description" => "Some useful description about your strategy",
"accountId" => "105646d8-8c97-4d4d-9b74-413bd66cd4ed"
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->removeStrategy("strategid");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Using legacy method (deprecated)
return $copyfactory->subscribers();
// Using infinite scroll pagination (recommended)
return $copyfactory->subscribersWithInfiniteScroll([
' 'offset' => 0
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->subscriber("subscriberiId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->updateSubscriber("subsciberId", [
'name' => "Copy Trade Subscriber",
'subscriptions' => [
[
'strategyId' => 'dJZq',
'multiplier' => 1,
]
]
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->removeSubscriber("subsciberId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $copyfactory->deleteSubscription("subsciberId", "strategyId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$webhook = $copyfactory->createWebhook("strategyId", [
'symbolMapping' => [
['from' => 'EURUSD.m', 'to' => 'EURUSD']
],
'magic' => 100
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$copyfactory->updateWebhook("strategyId", "webhookId", [
'symbolMapping' => [
['from' => 'EURUSD.m', 'to' => 'EURUSD'],
['from' => 'BTCUSD.m', 'to' => 'BTCUSD']
],
'magic' => 100
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Infinite scroll pagination
$webhooks = $copyfactory->webhooksWithInfiniteScroll("strategyId");
// Classic pagination
$webhooks = $copyfactory->webhooksWithClassicPagination("strategyId", [
'limit' => 10,
'offset' => 0
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$copyfactory->deleteWebhook("strategyId", "webhookId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$strategyId = "yd24";
$providerAccountId = "Enter your provider account ID";
$subAccountId = "Enter Subscriber Account ID";
return $copyfactory->copy($providerAccountId, $subAccountId, $strategyId);
/*
* You can ommit the strategy Id and just copy the trade
* The package will create a strategy as part of the copy process.
*/
return $copyfactory->copy($providerAccountId, $subAccountId);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\MetaStats;
$stats = new MetaStats('AUTH_TOKEN');
try {
return $stats->metrics("accountId");
// You can pass a boolean as second parameter if you want to essage());
return $response->message;
}
try {
return $stats->openTrades("accountId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
return $stats->accountTrades("accountId", "2020-01-01 00:00:00.000", "2021-01-01 00:00:00.000");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\ProvisioningProfileApi;
$provisioning = new ProvisioningProfileApi('AUTH_TOKEN');
try {
$profile = $provisioning->createProfile([
'name' => 'My profile',
'version' => 5, // 4 for MT4, 5 for MT5
'brokerTimezone' => 'EET',
'brokerDSTSwitchTimezone' => 'EET'
]);
// Upload servers.dat file for MT5 (or .srv file for MT4)
$provisioning->uploadFile($profile['id'], 'servers.dat', '/path/to/servers.dat');
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Infinite scroll pagination
$profiles = $provisioning->getProfilesWithInfiniteScroll([
'limit' => 10,
'offset' => 0,
'query' => 'ICMarketsSC-MT5',
'version' => 5
]);
// Classic pagination
$result = $provisioning->getProfilesWithClassicPagination([
'limit' => 10,
'offset' => 0
]);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Get profile by ID
$profile = $provisioning->getProfile("profileId");
// Update profile
$provisioning->updateProfile("profileId", [
'name' => 'New name'
]);
// Delete profile
$provisioning->deleteProfile("profileId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\TokenManagementApi;
$tokenManagement = new TokenManagementApi('AUTH_TOKEN');
try {
$narrowedToken = $tokenManagement->narrowDownTokenApplications(
['trading-account-management-api', 'metastats-api'],
24 // validity in hours
);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$narrowedToken = $tokenManagement->narrowDownTokenRoles(
['reader'], // read-only access
24
);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$narrowedToken = $tokenManagement->narrowDownTokenResources(
[['entity' => 'account', 'id' => 'account-id']],
24
);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$narrowedToken = $tokenManagement->narrowDownToken([
'applications' => ['metaapi-api'],
'roles' => ['reader'],
'resources' => [['entity' => 'account', 'id' => 'account-id']]
], 24);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$manifest = $tokenManagement->getAccessRules();
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\RiskManagementApi;
$riskManagement = new RiskManagementApi('AUTH_TOKEN');
try {
// Create a tracker
$tracker = $riskManagement->createTracker("accountId", [
'name' => 'Test tracker',
'period' => 'day',
'absoluteDrawdownThreshold' => 100
]);
// Get all trackers
$trackers = $riskManagement->getTrackers("accountId");
// Get tracker by ID
$tracker = $riskManagement->getTracker("accountId", "trackerId");
// Update tracker
$riskManagement->updateTracker("accountId", "trackerId", [
'name' => 'Updated name'
]);
// Delete tracker
$riskManagement->deleteTracker("accountId", "trackerId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Get tracker events
$events = $riskManagement->getTrackerEvents(
"2022-04-13 09:30:00.000",
"2022-05-14 09:30:00.000",
['accountId' => 'account-id', 'trackerId' => 'tracker-id']
);
// Get tracking statistics
$statistics = $riskManagement->getTrackingStatistics("accountId", "trackerId");
// Get equity chart
$equityChart = $riskManagement->getEquityChart("accountId", [
'startTime' => '2022-04-13 09:30:00.000',
'endTime' => '2022-05-14 09:30:00.000'
]);
// Get period statistics
$periodStats = $riskManagement->getPeriodStatistics("accountId", "trackerId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\AccountApi;
$account = new AccountApi('AUTH_TOKEN');
try {
// Note: preset field should be base64-encoded preset file
$expert = $account->createExpertAdvisor("accountId", "expertId", [
'period' => '1h',
'symbol' => 'EURUSD',
'preset' => 'a2V5MT12YWx1ZTEKa2V5Mj12YWx1ZTIKa2V5Mz12YWx1ZTMKc3VwZXI9dHJ1ZQ'
]);
// Upload EA file
$account->uploadExpertAdvisorFile("accountId", "expertId", "/path/to/custom-ea");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Get all expert advisors
$experts = $account->getExpertAdvisors("accountId");
// Get expert advisor by ID
$expert = $account->getExpertAdvisor("accountId", "expertId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Update expert advisor
$account->updateExpertAdvisor("accountId", "expertId", [
'period' => '4h',
'symbol' => 'EURUSD',
'preset' => 'a2V5MT12YWx1ZTEKa2V5Mj12YWx1ZTIKa2V5Mz12YWx1ZTMKc3VwZXI9dHJ1ZQ'
]);
$account->uploadExpertAdvisorFile("accountId", "expertId", "/path/to/custom-ea");
// Delete expert advisor
$account->deleteExpertAdvisor("accountId", "expertId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\AccountApi;
$account = new AccountApi('AUTH_TOKEN');
try {
// Get latest 1000 candles
$candles = $account->getHistoricalCandles("accountId", "EURUSD", "1m", null, 1000);
// Get candles from specific time
$candles = $account->getHistoricalCandles(
"accountId",
"EURUSD",
"1m",
"2021-05-01 00:00:00.000",
1000
);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
// Get latest 1000 ticks
$ticks = $account->getHistoricalTicks("accountId", "EURUSD", null, 0, 1000);
// Get ticks from specific time with offset
$ticks = $account->getHistoricalTicks(
"accountId",
"EURUSD",
"2021-05-01 00:00:00.000",
5,
1000
);
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\DemoAccountGeneratorApi;
$generator = new DemoAccountGeneratorApi('AUTH_TOKEN');
try {
$demoAccount = $generator->createMt4DemoAccount([
'balance' => 100000,
'accountType' => 'type',
'email' => '[email protected] ',
'leverage' => 100,
'serverName' => 'Exness-Trial4',
'name' => 'Test User',
'phone' => '+12345678901',
'keywords' => ["Exness Technologies Ltd"]
]);
// Optionally specify provisioning profile ID
$demoAccount = $generator->createMt4DemoAccount([
'balance' => 100000,
'accountType' => 'type',
'email' => '[email protected] ',
'leverage' => 100,
'serverName' => 'Exness-Trial4',
'name' => 'Test User',
'phone' => '+12345678901'
], "profileId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
try {
$demoAccount = $generator->createMt5DemoAccount([
'accountType' => 'type',
'balance' => 100000,
'email' => '[email protected] ',
'leverage' => 100,
'serverName' => 'ICMarketsSC-Demo',
'keywords' => ["Raw Trading Ltd"]
]);
// Optionally specify provisioning profile ID
$demoAccount = $generator->createMt5DemoAccount([
'accountType' => 'type',
'balance' => 100000,
'email' => '[email protected] ',
'leverage' => 100,
'serverName' => 'Exness-Trial4',
'name' => 'Test User',
'phone' => '+12345678901'
], "profileId");
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\ManagerApi;
$manager = new ManagerApi('AUTH_TOKEN');
try {
// GET request
$result = $manager->get('servers', ['limit' => 10]);
// POST request
$result = $manager->post('servers', ['name' => 'My Server']);
// PUT request
$result = $manager->put('servers/serverId', ['name' => 'Updated Name']);
// DELETE request
$result = $manager->delete('servers/serverId');
} catch (\Throwable $th) {
$response = json_decode($th->getMessage());
return $response->message;
}
use Oyi77\MetaapiCloudPhpSdk\Support\LatencyMonitor;
$monitor = new LatencyMonitor();
// Record latencies
$monitor->recordTradeLatency(150.5);
$monitor->recordRequestLatency(45.2);
$monitor->recordUpdateLatency(120.0);
$monitor->recordQuoteLatency(80.3);
// Get latency arrays
$tradeLatencies = $monitor->getTradeLatencies();
$requestLatencies = $monitor->getRequestLatencies();
// Get statistics
$tradeStats = $monitor->getTradeLatencyStats();
// Returns: ['count' => 1, 'min' => 150.5, 'max' => 150.5, 'avg' => 150.5, 'median' => 150.5]
$requestStats = $monitor->getRequestLatencyStats();
// Returns: ['count' => 1, 'min' => 45.2, 'max' => 45.2, 'avg' => 45.2, 'median' => 45.2]
// Clear all records
$monitor->clear();
use Oyi77\MetaapiCloudPhpSdk\Support\Logger;
// Enable logging with PSR-3 logger
use Psr\Log\LoggerInterface;
$psrLogger = new YourPSR3Logger();
Logger::enable($psrLogger);
// Or enable file logging
Logger::enableFileLogging('./logs/metaapi.log');
// Use logging
Logger::info('API request completed', ['endpoint' => '/accounts']);
Logger::debug('Debug information', ['data' => $data]);
Logger::warning('Warning message');
Logger::error('Error occurred', ['error' => $error]);
// Disable logging
Logger::disable();
use Oyi77\MetaapiCloudPhpSdk\Support\Pagination;
// Get items from paginated response
$accounts = $account->readAllWithClassicPagination(['limit' => 10, 'offset' => 0]);
$items = Pagination::getItems($accounts);
// Get total count (for classic pagination)
$totalCount = Pagination::getCount($accounts);
// Check if there are more pages
$hasMore = Pagination::hasMore($accounts, 10);
// Calculate total pages
$totalPages = Pagination::getTotalPages($accounts, 10);
composer test