So far, these tutorials have mostly focused on building charts, reporting tools, and (very rudimentary) automated trading systems. For this tutorial, we introduce a UserForm object with VBA to create a trade ticket which sends market orders to the OpenAPI for the selected instrument. The basis of this tool is the search functionality developed in Tutorial 1, which is extended by adding a TRADE action on the rightmost side, and a subscription to the /trade/v1/messages/ endpoint at the bottom, which we will use to keep track of the trades that are sent to the OpenAPI.
Most of the process however takes place behind the scenes in VBA, which automatically picks up the instrument details, populates the trade ticket, adjusts the contents based on the user's input, and sends the trade to the OpenAPI. The finished product looks as follows:
Requirements
For this spreadsheet to work correctly, a number of requirements need to be met:
- The instrument universe is limited to CFDs, Stocks, Bonds, FxSpot and Funds to simplify the trade ticket, which only sends market orders for now.
- Account information is loaded on a separate screen, which allows the user to choose the account he wishes to trade on in the main screen.
- The spreadsheet loads the trade ticket with the relevant instrument when the user clicks on a cell marked TRADE.
- Depending on the choices the user makes, the trade ticket updates the information on the screen and keeps track of the values that need to be sent to the OpenAPI. Buttons appear only when valid data is entered, and a warning will be shown when the user tries to enter non-sensible input.
- When the user clicks Place Market Order, VBA sends the order to the OpenAPI and shows the response in a separate popup, which in turn closes the trade ticket when confirmed.
- To keep track of the orders, a simple subscription function is used, which automatically updates with the latest trade messages.
As described above, most of the work is done within the trade ticket's VBA. which will be the main focus of this tutorial.
VBA solution
The VBA that drives the trade ticket consists of two parts:
- Keeping track of the user's actions and initializing the trade ticket with the correct information from the search results when the user hits TRADE.
- Serving the trade UserForm and sending the order to the OpenAPI.
The first part is relatively simple, and will be contained within the Trade worksheet. Key points in this script are:
- Every time a cell selection is changed, and the total number of selected cells equals 1, VBA checks whether the text in the cell is equal to "TRADE". Only then is the trade ticket launched.
- For convenience, the trade ticket is opened in the center of the Excel window.
- Required parameters (assettype and symbol) are pre-loaded.
- The title of the ticket is changed according to which instrument is selected.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim uic As Long
Dim assettype As String
Dim desc As String
Dim symbol As String
Dim dir As String
If Target.CountLarge = 1 Then 'if the selection is a single cell
If Target.Text = "TRADE" Then 'when TRADE is clicked
uic = Target.Offset(0, -4).Value 'assign UIC
assettype = Target.Offset(0, -5).Value 'assign AssetType
symbol = Target.Offset(0, -6).Value 'assign Symbol
desc = Target.Offset(0, -3).Value 'assign description
With Ticket 'launch trade ticket
'load trade ticket in the center of the Excel window
.StartUpPosition = 0
.Left = Application.Left + (0.5 * Application.Width) - (0.5 * .Width)
.Top = Application.Top + (0.5 * Application.Height) - (0.5 * .Height)
'load parameters
.Caption = "Trade: " + desc
.symbollabel.Caption = symbol
.assettypelabel.Caption = assettype
End With
'display ticket
Ticket.Show
End If
End If
End Sub
Next up, the trade ticket itself. The first step is to put the panel together using the VBA Toolbox to add all required elements.
And, finally, the following VBA to make it behave correctly. The designed user flow through this script is as follows:
- After the user opens the ticket, the first choice to be made is whether to buy or sell the selected instrument. Depending on the user's choice, the UI will automatically disable the opposite of the user's choice and flips back and forward between the two when the user keeps clicking the buy and sell buttons.
- As soon as the user chooses the order direction, the Amount input box is displayed, together with a summary box labeled Order.
- The user now enters the required amount, which cannot be anything other than a number.
- The user clicks Place Market Order, which executes the OpenAPI call and checks to verify whether the order was received correctly.
- The returned message is shown in a separate box, which in turn closes the trade ticket when the user hits OK.
Private Sub buybutton_Click()
'show direction
orderlabel.Visible = True
amounttext.Visible = True
amountvalue.Visible = True
ordertext.Visible = True
'logic to toggle buy/sell direction
If buybutton.Value = True Then
sellbutton.Value = False
dir = "BUY"
End If
If buybutton.Value = False Then
sellbutton.Value = True
dir = "SELL"
End If
'update direction text on ticket
orderlabel.Caption = dir + " " + CStr(amountvalue.Value) + " " + symbollabel.Caption
End Sub
Private Sub sellbutton_Click()
orderlabel.Visible = True
amounttext.Visible = True
amountvalue.Visible = True
ordertext.Visible = True
'logic to toggle buy/sell direction
If sellbutton.Value = True Then
buybutton.Value = False
dir = "SELL"
End If
If sellbutton.Value = False Then
buybutton.Value = True
dir = "BUY"
End If
'update direction text on ticket
orderlabel.Caption = dir + " " + CStr(amountvalue.Value) + " " + symbollabel.Caption
End Sub
Private Sub amountvalue_Change()
'update direction text on ticket
orderlabel.Caption = dir + " " + CStr(amountvalue.Value) + " " + symbollabel.Caption
placeorder.Visible = True
'check whether the input value is valid
If Not IsNumeric(amountvalue.Value) Then
If amountvalue.Value <> "" Then
MsgBox "Please a number.", , "Error!"
amountvalue.Value = 0
End If
End If
End Sub
Private Sub placeorder_Click()
uic = ActiveCell.Offset(, -4)
orderlabel.Caption = "Sending " & dir & " order.."
body = "{" & _
"'AccountKey':'" & [accountkey] & "', " & _
"'Amount':" & amountvalue.Value & ", " & _
"'AssetType':'" & assettypelabel.Caption & "', " & _
"'BuySell':'" & dir & "', " & _
"'Uic':" & uic & ", " & _
"'OrderType':'Market', " & _
"'OrderDuration':{'DurationType':'DayOrder'}, " & _
"'ManualOrder':true" & _
"}"
trade = Application.Run("OpenAPIPost", "trade/v2/orders", body)
'check if order was placed successfully
If InStr(3, trade, "OrderId") = 3 Then
MsgBox "Order placed successfully.", , "Order placed!"
Else
MsgBox trade, , "Error!"
End If
'close trade ticket after confirmation
Unload Ticket
End Sub

