REST Sample Codes¶
Backtest and Strategy Sample Codes¶
bt backtest
using FXCM historical data. What is bt?QSTrader
using FXCM data. What is QSTrader?RSI Strategy
Moving Average Crossover Strategy
- Video demonstration on how to backtest strategies in Visual Studio using FXCM data on QuantConnect LEAN platform.
PHP¶
FxcmRest
is a library for event-driven trading with FXCM over RestAPI using ReactPHP
.
Requirements¶
PHP 7.0.2+
Installation¶
The recommended way to install FxcmRest is through Composer.
This command will install the latest stable version:
$ composer require fxcm/fxcmrest
Usage¶
As FXCM Rest API requires you to keep Socket.IO connection open through the whole time it is used, this library must be run within a php script and not as part of php generated website.
Interaction can be done either by using a console or through HTTP requests handled directly by the php script for example with \React\HTTP
.
Main class of the library is \FxcmRest\FxcmRest
. It must be instantiated with two objects:
\React\EventLoop\LoopInterface
\FxcmRest\Config
Configuration class \FxcmRest\Config
must be instantiated with an array containing at least the two following parameters:
host
token
Configuration Parameters¶
protocol
- either\FxcmRest\Protocol::HTTPS
(default) or\FxcmRest\Protocol::HTTP
host
- eitherapi.fxcm.com
for Real accounts orapi-demo.fxcm.com
for Demo accountsport
- port number.443
defaulttoken
- 40 char hexadecimal string
Functions¶
connect() : null
- Opens a connection to the server. When connection is complete,
connected
signal will be emitted.
disconnect() : null
- Disconnects from the server. When disconnection is complete,
disconnected
signal will be emitted.
socketID() : string
- If connected to the server, returns a string representing the socketID. If not connected, returns an empty string.
request(\FxcmRest\HttpMethod $method, string $path, array $arguments, callable $callback) : null
Sends a http request to the server. When request is completed,
$callback
will be called with two parameters:int
representing HTTP status code. 200 for OKstring
representing server answer body
on(string $signalName, callable $callback) : null
- Registers a
$callback
for a signal of$signalName
. For a list of signals and parameters that are passed with them please see Signals section.
Signals¶
connected
- Emitted when connection sequence is complete. After this socketID is valid and requests can be sent to the server. No parameters are passed.disconnected
- Emitted when connection to the server is closed. No parameters are passed.error
- Emitted on errors. Passes error description as string.[Offer,OpenPosition,ClosedPosition,Account,Summary,Properties]
- Emmited on trading table changes. Passes table update contents as JSON string. Requires subscription through/trading/subscribe
(EUR/USD,EUR/GBP,...)
- Emmited on price update. Passes the price update as a JSON string. Requires subscription through/subscribe
.
PHP Sample Code¶
<?php
require_once __DIR__ . '/vendor/autoload.php';
$loop = \React\EventLoop\Factory::create();
$config = new \FxcmRest\Config([
'host' => 'api-demo.fxcm.com',
'token' => 'YOUR_TOKEN',
]);
$counter = 0;
$rest = new \FxcmRest\FxcmRest($loop, $config);
$rest->on('connected', function() use ($rest,&$counter) {
$rest->request('POST', '/subscribe',
['pairs' => 'EUR/USD'],
function($code, $data) use ($rest,&$counter) {
if($code === 200) {
$rest->on('EUR/USD', function($data) use ($rest,&$counter) {
echo "price update: {$data}\n";
$counter++;
if($counter === 5){
$rest->disconnect();
}
});
}
}
);
});
$rest->on('error', function($e) use ($loop) {
echo "socket error: {$e}\n";
$loop->stop();
});
$rest->on('disconnected', function() use ($loop) {
echo "FxcmRest disconnected\n";
$loop->stop();
});
$rest->connect();
$loop->run();
?>
Python¶
Note
REST API Python code sample - fxcm-api-rest-python3-example. Clone this repository by clicking here.
Getting started¶
- Install Python.
- Run:
pip install -r requirements.txt
- Within the
fxcm_rest.json
file:- Set log path via the
logpath
field - Set
debugLevel
if desired - Set subscription lists if desired
- Set log path via the
- In the
fxcm_rest_client_sample.py
file:- Set your token and environment (demo/real)
Using Jupyter Notebook¶
- Install Python.
- Run:
pip install jupyter
(if you don’t have jupyter installed already) - Run:
pip install -r requirements.txt
- In this directory run:
jupyter notebook
- Start the
RestApiNotebook.ipynb
.
Details¶
This API exposes the methods of the REST API as a class, dealing with all of the common tasks involved with setting up connections and wiring callback listeners for you. In addition to that there are a few convenience methods.
A quick example is as follows:
import fxcm_rest_api_token
import time
trader = fxcm_rest_api_token.Trader('YOURTOKEN', 'prod')
trader.login()
#### Open Market Order
# query account details and use the first account found
accounts = trader.get_model("Account")
account_id = accounts['accounts'][0]['accountId']
# Open 10 lots on USD/JPY for the first account_id found.
response = trader.open_trade(account_id, "USD/JPY", True, 10)
if response['status']:
# close all USD/JPY trades.
response = trader.close_all_for_symbol("USD/JPY")
#### Historical Data request
basic = trader.candles("USD/JPY", "m1", 5)
print(basic)
date_fmt = trader.candles("USD/JPY", "m1", 5, dt_fmt="%Y/%m/%d %H:%M:%S")
print(date_fmt)
date_fmt_headers = trader.candles_as_dict("USD/JPY", "m1", 3, dt_fmt="%Y/%m/%d %H:%M:%S")
print(date_fmt_headers)
##### Price subscriptions
subscription_result = trader.subscribe_symbol("USD/JPY")
# Define alternative price update handler and supply that.
def pupdate(msg):
print("Price update: ", msg)
subscription_result = trader.subscribe_symbol("USD/JPY", pupdate)
counter = 1
while counter < 60:
time.sleep(1)
counter += 1
Candles¶
All calls to candles allow either instrument name
, or offerId
. They also allow the From
and To
to be specified as timestamp or a date/time format that will be interpreted (“2017/08/01 10:00”, “Aug 1, 2017 10:00”, etc.).
In addition to instrument_id
, response
, period_id
and candles
, a headers
field (not documented in the API notes) is returned, representing the candle fields.
basic
for item in basic['candles']:
print item
[1503694500, 109.317, 109.336, 109.336, 109.314, 109.346, 109.366, 109.373, 109.344, 72]
[1503694560, 109.336, 109.321, 109.337, 109.317, 109.366, 109.359, 109.366, 109.354, 83]
[1503694620, 109.321, 109.326, 109.326, 109.316, 109.359, 109.358, 109.362, 109.357, 28]
date_fmt
for item in date_fmt['candles']:
print item
[1503694500, 109.317, 109.336, 109.336, 109.314, 109.346, 109.366, 109.373, 109.344, 72, '2017/08/26 05:55:00']
[1503694560, 109.336, 109.321, 109.337, 109.317, 109.366, 109.359, 109.366, 109.354, 83, '2017/08/26 05:56:00']
[1503694620, 109.321, 109.326, 109.326, 109.316, 109.359, 109.358, 109.362, 109.357, 28, '2017/08/26 05:57:00']
date_fmt_headers
for item in date_fmt_headers['candles']:
print item
Headers(timestamp=1503694620, bidopen=109.321, bidclose=109.326, bidhigh=109.326, bidlow=109.316, askopen=109.359, askclose=109.358, askhigh=109.362, asklow=109.357, tickqty=28, datestring='2017/08/26 05:57:00')
Headers(timestamp=1503694680, bidopen=109.326, bidclose=109.312, bidhigh=109.326, bidlow=109.31, askopen=109.358, askclose=109.374, askhigh=109.376, asklow=109.358, tickqty=42, datestring='2017/08/26 05:58:00')
Headers(timestamp=1503694740, bidopen=109.312, bidclose=109.312, bidhigh=109.312, bidlow=109.31, askopen=109.374, askclose=109.374, askhigh=109.374, asklow=109.372, tickqty=4, datestring='2017/08/26 05:59:00')
for item in date_fmt_headers['candles']:
print "%s: Ask Close [%s], High Bid [%s] " % (item.datestring, item.askclose, item.bidhigh)
2017/08/26 05:57:00: Ask Close [109.358], High Bid [109.326]
2017/08/26 05:58:00: Ask Close [109.374], High Bid [109.326]
2017/08/26 05:59:00: Ask Close [109.374], High Bid [109.312]
subscribe_symbol - default
{u'Updated': 1504167080, u'Rates': [110.467, 110.488, 110.629, 110.156], u'Symbol': u'USD/JPY'}
{u'Updated': 1504167081, u'Rates': [110.469, 110.49, 110.629, 110.156], u'Symbol': u'USD/JPY'}
subscribe_symbol - overridden
Price update: {"Updated":1504167248,"Rates":[110.446,110.468,110.629,110.156],"Symbol":"USD/JPY"}
Price update: {"Updated":1504167250,"Rates":[110.446,110.468,110.629,110.156],"Symbol":"USD/JPY"}
Note
This is for personal use and abides by our EULA. For more information, you may contact us at api@fxcm.com
Disclaimer:
CFDs are complex instruments and come with a high risk of losing money rapidly due to leverage. 73.62% of retail investor accounts lose money when trading CFDs with this provider. You should consider whether you understand how CFDs work and whether you can afford to take the high risk of losing your money. High Risk Investment Notice: Trading Forex/CFD’s on margin carries a high level of risk and may not be suitable for all investors as you could sustain losses in excess of deposits. The products are intended for retail, professional and eligible counterparty clients. For clients who maintain account(s) with Forex Capital Markets Limited (“FXCM LTD”), retail clients could sustain a total loss of deposited funds but are not subject to subsequent payment obligations beyond the deposited funds and professional clients could sustain losses in excess of deposits. Prior to trading any products offered by FXCM LTD, inclusive of all EU branches, FXCM Australia Pty. Limited, FXCM South Africa (PTY) Ltd, any affiliates of aforementioned firms, or other firms within the FXCM group of companies [collectively the “FXCM Group”], carefully consider your financial situation and experience level. If you decide to trade products offered by FXCM Australia Pty. Limited (“FXCM AU”) (AFSL 309763), you must read and understand the Financial Services Guide, Product Disclosure Statement and Terms of Business. Our Forex/CFD prices are set by FXCM, are not made on an Exchange and are not governed under the Financial Advisory and Intermediary Services Act. The FXCM Group may provide general commentary which is not intended as investment advice and must not be construed as such. Seek advice from a separate financial advisor. The FXCM Group assumes no liability for errors, inaccuracies or omissions; does not warrant the accuracy, completeness of information, text, graphics, links or other items contained within these materials. Read and understand the Terms and Conditions on the FXCM Group’s websites prior to taking further action.”