Seamlessly integrate OANDA Excel RTD with MT4 to monitor real-time pricing, analyse trading data, manage positions, and execute trades directly from Excel.
Using OANDA Excel RTD with MT4
With OANDA Excel RTD, you can seamlessly link your MT4 account with Microsoft Excel to monitor your account status, track currency rates, and analyse trading activity in real time.
By leveraging Excel’s RTD function, traders can build fully customised charts, manage open positions and pending orders, and display live pricing data.
Price history data can also be retrieved, giving you the flexibility to perform detailed backtesting and analysis.
- Position management
- Live rates
- Price history data retrieval
Combined with VBA (Visual Basic for Applications), OANDA Excel RTD allows you to place trades, modify orders, and close positions directly from Excel.
This integration enables traders to collect a wide range of data and adapt it creatively to suit their individual strategies.
How to use OANDA Excel RTD
OANDA Excel RTD is structured as an EA, so you need to ensure that automated trading is enabled in MT4 before using it.
In the Navigator window, double-click the OANDA Excel RTD or drag and drop it onto a chart.
A settings window will appear:
Make sure that both “Allow live trading” and “Allow DLL imports” are checked, then click “OK”.
A window will display your account number, which is the link between MT4 and Excel.
At this point, the MT4 side of the set-up is complete.
Next, you will need to enter functions in Excel.
Basic RTD function structure
To display data, enter the following formula, replacing “account number” with your own account number and “property name” with the specific data you want to display:
=RTD("FXBlueLabs.ExcelRTD",,"account number","property name")
Property names
The following property names can be used to retrieve data about the account, price, symbol (the currency pair), and tickets:
Account data
=RTD("FXBlueLabs.ExcelRTD",,"156734","currency")
- currency: account currency
- balance: account balance
- equity: account equity
- pl: floating profit/loss
- usedmargin: margin in use
- freemargin: free margin
- tickets: number of tickets (open positions and pending orders)
Price and symbol data
=RTD("FXBlueLabs.ExcelRTD",,"156734","askEURUSD")
- bidSymbol: Bid price of the currency pair (symbol)
- askSymbol: Ask price
- highSymbol: daily high
- lowSymbol: daily low
- symbols: number of currency pairs
- sNumber: symbol name e.g. EURUSD, corresponding to the number entered
Ticket data
=RTD("FXBlueLabs.ExcelRTD",,"156734","t2s")
You can retrieve detailed information about open positions and pending orders.
Ticket numbers are assigned in ascending order, starting from 1 for the oldest.
- tNumbert: ticket number
- tNumbera: action (Buy, Sell, Buylimit, Selllimit, Buystop, Sellstop)
- tNumbers: symbol name
- tNumberv: trade volume
- tNumbernpl: net profit/loss (including swaps)
- tNumberpl: trade profit/loss
- tNumberswap: swap profit/loss
- tNumbercomm: commission
- tNumbersl: stop-loss price
- tNumbertp: take-profit price
- tNumberop: open or entry price
- tNumbercp: current price
- tNumbercm: order comment
- tNumbermg: magic number
Retrieving price history
The formula used is as follows (@bh = bar history):
=RTD("FXBlueLabs.ExcelRTD",,"account number","@bh,symbol,timeframe,price type,shift")
So to display the current H1 high for EUR/USD, the formula would be:
`=RTD("FXBlueLabs.ExcelRTD",,"156734","@bh,EURUSD,H1,high,0")`
Supported timeframe values include:
- M1: 1 minute
- M2: 2 minutes
- M3: 3 minutes
- M4: 4 minutes
- M5: 5 minutes
- M6: 6 minutes
- M10: 10 minutes
- M15: 15 minutes
- M30: 30 minutes
- H1: 60 minutes
- H2: 120 minutes
- H3: 180 minutes
- H4: 240 minutes
- H6: 360 minutes
- H8: 480 minutes
- D1: 1440 minutes
- D2: 2880 minutes
- W1: 7200 minutes
Information about each bar timeframe can be requested as follows:
- open: open price
- high: high price
- low: low price
- close: close price
- range: the price range from high to lowest values
- median: the average of the high and low prices
- typical: the average of the high, low, and close prices
- weighted: a weighted average where the close price counts twice compared with the high and low
- change: the price movement from the open price
- abschange: the absolute value of the price movement from the open price
- time: the start time of the selected timeframe
Technical indicator calculations
OANDA Excel RTD offers built-in technical indicator calculations, which you can request using different formulae.
For example, entering the following formula will display the RSI value for 14 periods on the GBP/USD five-minute chart:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@rsi,GBPUSD,M5,14,0")
The general formula for displaying technical indicators is as follows:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@IndicatorName,Symbol,Timeframe,Parameters,ShiftCount (0 for current bar)")
A shift count of `0` displays the value for the current bar.
Entering `1` shows the value for the previous bar.
Setting up technical indicators
Simple moving average (SMA)
The formula for calculating the SMA is as follows:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@sma,Symbol,Timeframe,PriceType,Period,ShiftCount")
You can select the price type, such as close or median.
In the following example, the formula displays the median price, which is the average of the high and low for the last 10 bars on GBP/USD M5:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@sma,GBPUSD,M5,median,10,0")
Exponential moving average (EMA)
The formula for calculating the EMA is similar to that of the SMA:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@ema,Symbol,Timeframe,PriceType,Period,ShiftCount")
Example using the median price:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@ema,GBPUSD,M5,median,10,0")
Smoothed moving average (SMMA)
The SMMA formula follows the same structure, except for the indicator name. This example calculates the average of the close prices of the last 21-bar timeframe on GBP/USD H1:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@smma,GBPUSD,H1,close,21,0")
Weighted / Linear-Weighted moving average (WMA / LWMA)
The formula is identical to that of the SMA and EMA, with only the indicator name changed. This example calculates the average of the ranges of the last 21 bars on GBP/USD D1:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@lwma,GBPUSD,1440,range,21,0")
MACD and MACD signal value
To calculate the MACD, use the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@macd,Symbol,Timeframe,PriceType,FastEMA,SlowEMA,SignalPeriod,ShiftCount")
Here’s an example which calculates the MACD for GBP/USD M30 using the 12-bar fast EMA and a 26-bar slow EMA, applying the calculation to the high price of each bar:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@macd,GBPUSD,30,high,12,26,9,0")
To calculate the smoothed signal value, replace @macd with @macdsig.
Average true range (ATR)
To calculate the ATR, use the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@atr,Symbol,Timeframe,Period,ShiftCount")
This example calculates the ATR of the last 21 bars on GBP/USD D1:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@atr,GBPUSD,D1,21,0")
RSI
To calculate the RSI, use the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@rsi,Symbol,Timeframe,Period,ShiftCount")
This example calculates the 14-bar RSI on the USD/JPY M3:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@rsi,USDJPY,H1,14,0")
Stochastic oscillator
This formula is used to calculate the stochastic oscillator using the standard parameters of 5,3,3 (replace @stoch with `@stochslow` for the slowed signal value):
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@stoch,Symbol,Timeframe,Parameters,ShiftCount")
The following example calculates the oscillator on the USD/JPY H1 bars using the standard parameters of 5,3,3:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@stochslow,USDJPY,H1,5,3,3,0")
Bollinger bands
The formula for calculating Bollinger bands using the @bbupper (upper) or @bblower (lower) indicators:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@bbupper (or @bblower),Symbol,Timeframe,PriceType,Period,StdDev,ShiftCount")
This example calculates the upper band on the GBP/USD M10, using an average of the close prices on the last 30 bars with two standard deviations:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@bbupper,GBPUSD,10,close,30,2,0")
Volatility or Standard deviation
The @vol indicator is used to calculate volatility with the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@vol,Symbol,Timeframe,PriceType,Period,ShiftCount")
This example calculates the volatility of the last 21-bar ranges on GBP/USD M10:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@vol,GBPUSD,10,close,21,0")
Commodity Channel Index (CCI)
To calculate the CCI, use the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@cci,Symbol,Timeframe,PriceType,Period,ShiftCount")
This example calculates the CCI using the typical bar price for the last 14 bars on the EUR/USD H1:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@cci,EURUSD,60,typical,14,0")
Highest high over a set period
To calculate the highest high, use the following formula:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@high,Symbol,Timeframe,high,CandleCount,ShiftCount")
Here is an example that calculates the highest high during the last 20 GBP/USD D1 bars:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@high,GBPUSD,D1,high,20,0")
Lowest low over a set period
Conversely, you can use this formula to find the lowest low:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@low,Symbol,Timeframe,low,CandleCount,ShiftCount")
In this example, the formula calculates the lowest low during the last 20 GBP/USD D1 bars:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@low,GBPUSD,D1,low,20,0")
Swing points (Fractals): swing high and swing low
Calculate recent swing points using these formulas:
For a swing point with lower highs on either side of the bar, use @swingh:
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@swingh ,Symbol,Timeframe,high,SwingCount,ShiftCount")
For a swing point with higher lows, use @swingl
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@swingl,Symbol,Timeframe,low,SwingCount,ShiftCount")
For fractals, the shift count can be either `0` or `1`.
- `0` ignores the current bar and uses confirmed data.
- `1` includes the current bar in the calculation.
This example finds the most recent swing high price on GBP/USD D1 using a 5-bar swing (= 2 bars either side of the swing point):
=RTD("FXBlueLabs.ExcelRTD",,"156734","@swingh,GBPUSD,D1,high,2,0")
Keltner channel upper and lower bands
This formula is used to calculate Keltner channels (EMA +/- ATR):
=RTD("FXBlueLabs.ExcelRTD",,"AccountNumber","@keltlower,Symbol,Timeframe,PriceType,EMAPeriod,ATRPeriod,ATRMultiplier,ShiftCount")
In this example, the lower Keltner channel is calculated on GBP/USD H1 using a 20-bar EMA, minus half of a 10-bar ATR:
=RTD("FXBlueLabs.ExcelRTD",,"156734","@keltlower,GBPUSD,60,close,20,10,0.5,0")
Displaying symbol names
On OANDA server, symbol or currency pair names are displayed with a suffix, such as `USDJPY.oj1m`.
By default, OANDA Excel RTD removes these suffixes and displays only the base format, e.g., `USDJPY`.
If you prefer to display the full format, such as `USDJPY.oj1m`, deselect the option “Use standardised symbol names” in MT4.
Sending trading commands
With OANDA Excel RTD, you can send trading commands directly from Excel using VBA code.
You can also retrieve the same data via RTD functions.
These functions are supported not only in Excel VBA ,but also in any programming language that supports COM.
Reading data in VBA code
You can read account data by using the FXBlueLabs.ExcelReader object.
Set reader = CreateObject("FXBlueLabs.ExcelReader")
reader.Connect ("156734")
MsgBox reader.Read("balance")
This creates an instance of the FXBlueLabs.ExcelReader object.
It connects to a specific account number using the Connect() function.
You can then obtain account-related data by using the Read() function.
The property names used in the Read() function are the same as those used in RTD formulas.
Checking if the reader is connected correctly
If the ExcelReader object has been created successfully, you can call the Connect() function even if OANDA Excel RTD is not actively running.
To check that data is available, use the Read() function to ensure that properties, such as the account balance, are not blank, or check the “LastUpdateTime” property to confirm that the timestamp is later than 1 January 2000.
Ensuring data consistency when reading multiple values
When retrieving multiple data points, especially ticket data, it is important to maintain consistency.
Consider the following code, which loops through a ticket list:
For i = 1 To reader.Read("tickets")
strSymbol = reader.Read("t" & i & "s")
vVolume = reader.Read("t" & i & "v")
Next
The following situation may occur:
- Initially, there are two open tickets.
If one of the tickets closes while the Read() function is called twice — that is, during the execution of the second and third lines — the ticket numbers may shift.
As a result, what was originally ticket 2 becomes ticket 1.
Consequently, at the end of the first loop, the strSymbol may hold the symbol of the ticket that is now closed, while vVolume shows the trade volume of the ticket that is still open.
To maintain consistency when retrieving multiple data points, use the Reader.ReaderLock() function.
This prevents any changes to the data until you release it with Reader.ReaderUnlock().
Example:
Reader.ReaderLock()
For i = 1 To reader.Read("tickets")
strSymbol = reader.Read("t" & i & "s")
vVolume = reader.Read("t" & i & "v")
Next
Reader.ReaderUnlock()
Don’t forget to call Reader.ReaderUnlock() after using Reader.ReaderLock().
Sending trading commands from Excel
By default, commands are turned off in OANDA Excel RTD.
To send commands, you need to tick the “Accept commands” checkbox in the settings.
If you do not enable this feature, all commands will return the following error message:
“ERR: Commands not allowed”
Use the FXBlueLabs.ExcelCommand object to send trading commands from Excel:
Set cmd = CreateObject("FXBlueLabs.ExcelCommand")
strResult = cmd.SendCommand("156734", "BUY", "s=EURUSD|v=10000", 5)
The SendCommand() function has four parameters:
- Account number (e.g. 156734)
- Command (action)
- Command parameters (symbol and trade volume)
- Timeout period (in seconds)
The SendCommand() function is synchronous.
It returns once the command has completed or the timeout period has expired.
Note: Timeout does not mean that the order has been withdrawn or cancelled.
It simply means that the broker or platform did not respond within the allowed time.
The function returns a string beginning with either:
- "OKAY:" if the command was successful, or
- "ERR:" if an error occurred.
The only exception to this is the “TEST” command, which returns the text "HELLO".
Command parameters
Command parameters are sent as a single string, separated by pipes |, comprising different settings in the name=value format.
The parameters can be listed in any order, and some are optional.
Example:
cmd.SendCommand("156734","BUY","s=EURUSD|v=10000",5)
Trading volumes are specified in cash amounts traded, not as lot sizes.
The format of the symbol name depends on whether the “Use standardised symbol names” option is enabled in RTD.
Command types
BUY and SELL
Parameters:
- s (compulsory): symbol name
- v (compulsory): trading volume
- sl (optional): stop-loss price for the new position
- tp (optional): take-profit price for the new position
- comment (optional): comment for the new position
- magic (optional): magic number for the new position
BUYLIMIT, SELLLIMIT, BUYSTOP and SELLSTOP
Parameters:
- s (compulsory): symbol name
- v (compulsory): trading volume
- price (compulsory): entry price for the pending stop/limit order
- sl (optional): stop-loss price for the new position
- tp (optional): take-profit price for the new position
- comment (optional): comment for the new position
- magic (optional): magic number for the new position
CLOSE
This command closes an open position or deletes a pending order.
Returns “OKAY”: if successful.
Parameter:
t (compulsory): ID of position to be closed/pending order to be deleted
PARTIALCLOSE
This command partially closes an open position.
If the specified size exceeds the open position, the full position is closed.
This command cannot be used for pending orders.
Parameters:
- t (compulsory): ID of position to be partially closed
- v (compulsory): trading volume to be closed
REVERSE
This command reverses an open position, e.g., closing an open sell and opening a new buy position.
Parameters:
- t (compulsory): ID of position to be reversed
- v (optional): volume for the new reversed position
- sl (optional): stop-loss price for the new position
- tp (optional): take-profit price for the new position
- comment (optional): comment for the new position
- magic (optional): magic number for the new position
CLOSESYMBOL
This command closes all positions and pending orders for a specific symbol.
Returns “OKAY”: if successful.
Parameter:
- s (compulsory): symbol name to close
CLOSEALL
Closes all open positions and pending orders across all symbols.
Returns “OKAY”: if successful.
Example:
cmd.SendCommand("156734","CLOSEALL","",20) '20-second timeout
ORDERSL
Modifies the stop-loss price on an open trade or pending order.
Parameters:
- t (compulsory): ID of the trade or pending order to be changed
- sl (compulsory): new stop-loss price (use 0 to delete any existing S/L)
ORDERTP
Modifies the take-profit price on an open trade or pending order.
Parameters:
- t (compulsory): ID of the trade or pending order to be changed
- tp (compulsory): new take-profit price (use 0 to delete any existing T/P)
ORDERMODIFY
Modifies both the stop-loss and take-profit levels for open trades or pending orders.
It can also change the entry price for pending orders.
Parameters:
- t (compulsory): ID of the trade or pending order to be changed
- p (compulsory when modifying pending orders): new entry price for pending orders
- sl (compulsory): new stop-loss price (use 0 to delete any existing S/L)
- tp (compulsory): new take-profit price (use 0 to delete any existing T/P)
Standard error messages
- ERR: Need account: account information is missing
- ERR: Need command: command is missing
- ERR: No listening app: RTD is not running for the specified account
- ERR: No response within timeout: no response from broker or platform within specified period
- ERR: Commands not allowed: “Allow commands” option disabled in RTD
- ERR: Unrecognised command: invalid command value
- ERR: Missing parameters: compulsory parameters are missing
Asynchronous commands
Commands can be sent asynchronously rather than blocking VBA execution until a command completes or times out.
Use the CheckAsyncResult() function to periodically check the result of the asynchronous action.
When the action is completed, or if you decide to cancel it, free up command memory by using the **FreeAsyncCommand** function.
Example:
Set cmd = CreateObject("FXBlueLabs.ExcelCommand")
lCommandId = cmd.SendCommandAsync("10915", "BUY", "s=EURUSD|v=10000", 60)
strResult = ""
While strResult = ""
strResult = cmd.CheckAsyncResult(lCommandId)
If strResult = "" Then MsgBox "Still waiting..."
Wend
cmd.FreeAsyncCommand (lCommandId)
The SendCommandAsync function uses the same four parameters as the SendCommand function.
However, instead of returning the command result directly, it returns a “command ID” that is later used with the CheckAsyncResult() and FreeAsyncCommand() functions.
Note that the SendCommandAsync() function still requires a timeout value.
After SendCommandAsync(), you must eventually call the FreeAsyncCommand() function, otherwise, the code may experience a small memory leak.
CheckAsyncResult() returns an empty string if the command is still running and the specified timeout has not been reached.
If the command is completed, it returns the same string response as SendCommand().