### Run a Tutorial Project
Source: https://github.com/tradovate/example-api-js/blob/main/README.md
Start a tutorial project after installing dependencies. Access the running project by navigating to localhost:8080 in your browser.
```bash
> yarn start
```
--------------------------------
### Install WebSocket Dependencies
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-05-WebSockets-Start/README.md
Navigate to the WebSocket tutorial directory and install project dependencies using yarn.
```bash
> cd c:/path/to/repo/tutorial/WebSockets/EX-5-WebSockets-Start
> yarn install
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/tradovate/example-api-js/blob/main/README.md
Install project dependencies using yarn. Navigate to the tutorial project's root directory before running this command.
```bash
> yarn install
```
--------------------------------
### Project Structure Overview
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
This illustrates the typical file and directory structure for the Tradovate API example projects.
```text
|-EX-0-Access-Start
|---src
|-----app.js
|-----connect.js
|-----services.js
|---babel.config.json
|---index.html
|---package.json
|---webpack.config.js
...
|-
```
--------------------------------
### Setup UI for Placing Orders
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-12-Calculating-Open-PL/README.md
This function sets up event listeners for buy and sell buttons to place market orders. It retrieves the primary account, validates symbol and quantity inputs, and then places the order via the API. It also synchronizes user data using the provided WebSocket socket.
```javascript
const setupUI = () => {
const setupUI = (socket) => {
const onClick = (buyOrSell = 'Buy') => async () => {
//first available account
const { name, id } = getAvailableAccounts()[0]
if(!$symbol.value || !$qty.value) return
let { orderId } = await tvPost('/order/placeOrder', {
action: buyOrSell,
symbol: $symbol.value,
orderQty: parseInt($qty.value, 10),
orderType: 'Market',
accountName: name,
accountId: id
})
console.log(orderId)
}
$buyBtn.addEventListener('click', onClick('Buy'))
$sellBtn.addEventListener('click', onClick('Sell'))
}
```
--------------------------------
### Initiate Fetch Request
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
This snippet shows the basic structure of initiating a fetch request to a specific endpoint. It's the starting point for making API calls from a web browser.
```javascript
const connect = () => {
fetch(DEMO_URL + '/auth/accesstokenrequest')
}
```
--------------------------------
### Subscribe to Chart Data
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-10-Chart-Data/README.md
Example of subscribing to real-time chart data using the socket.subscribe method with specific chart parameters.
```javascript
$getChart.addEventListener('click', async () => {
unsubscribe = await socket.subscribe({
url: 'md/getchart',
body: {
symbol: 'MNQZ1',
chartDescription: {
underlyingType: 'MinuteBar',
elementSize: 30,
elementSizeUnit: 'UnderlyingUnits',
withHistogram: false,
},
timeRange: {
asMuchAsElements: 20
}
},
subscription: (chart) => {
console.log(chart)
}
})
})
```
--------------------------------
### GET Request with tvGet
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-1-Simple-Request/README.md
Use tvGet for GET endpoints. It handles query string manipulation and JSON response decoding. The first parameter is the endpoint, and the optional second parameter is an object for the query string.
```javascript
//no parameters
const jsonResponseA = await tvGet('/account/list')
```
```javascript
//parameter object, URL will become '/contract/item?id=2287764'
const jsonResponseB = await tvGet('/contract/item', { id: 2287764 })
```
--------------------------------
### Connect Function with Time Penalty Handling
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-3-Time-Penalty/README.md
This function handles the time penalty response by checking for a 'p-ticket' and calling a retry function if present. It first checks for a valid existing access token before attempting to get a new one.
```javascript
export const connect = async (data) => {
const { token, expiration } = getAccessToken()
if(token && tokenIsValid(expiration)) {
console.log('Already have an access token. Using existing token.')
return
}
const authResponse = await tvPost('/auth/accesstokenrequest', data, false)
//added branch
if(authResponse['p-ticket']) {
await handleRetry(data, authResponse)
}
const {accessToken, expirationTime, } = await tvPost('/auth/accesstokenrequest', data, false)
setAccessToken(accessToken, expirationTime)
}
```
--------------------------------
### Get HTML Element References
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-10-Chart-Data/README.md
Obtain references to the HTML controls defined in the body for later use in event listeners and data retrieval.
```javascript
const main = async () => {
//...
const $getChart = document.getElementById('get-chart-btn')
const $symbol = document.getElementById('symbol')
const $type = document.getElementById('type')
const $nElements = document.getElementById('n-elements')
const $elemSize = document.getElementById('elem-size')
//...}
```
--------------------------------
### Authentication Request with tvPost
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-1-Simple-Request/README.md
This function uses tvPost to make an access token request. The third parameter 'false' is used to prevent the default Authentication header setup, which is necessary for the initial token request.
```javascript
//connect.js
export const connect = async (data) => {
const json = await tvPost('/auth/accesstokenrequest', data, false)
console.log(json)
}
```
--------------------------------
### Subscribe to Chart Data and Render
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-10-Chart-Data/README.md
Attaches an event listener to the 'Get Chart' button. On click, it subscribes to chart data via the 'md/getchart' WebSocket endpoint, processes incoming bar data, and renders a candlestick chart using CanvasJS.
```javascript
$getChart.addEventListener('click', async () => {
all_bars = []
if(unsubscribe) unsubscribe()
unsubscribe = await socket.subscribe({
url: 'md/getchart',
body: {
symbol: $symbol.value,
chartDescription: {
underlyingType: $type.value,
elementSize: parseInt($elemSize.value),
elementSizeUnit: 'UnderlyingUnits',
withHistogram: false,
},
timeRange: {
asMuchAsElements: parseInt($nElements.value)
}
},
subscription: chart => {
if(chart.eoh) {
console.log('end of history')
return
}
let stockChart = new CanvasJS.StockChart("outlet", {
title: {
text: `${$symbol.value} Chart`
},
charts: [
{
data: [
{
type: "candlestick", //Change it to "spline", "area", "column"
dataPoints : all_bars
}
]
}],
navigator: {
slider: {
minimum: new Date('2020 01 01'),
maximum: new Date()
}
}
});
chart.bars.forEach(bar => {
const { high, low, open, close, timestamp } = bar
all_bars.push({x: new Date(timestamp), y: [open, high, low, close]})
})
stockChart.render()
}
})
})
```
--------------------------------
### Import URLs and Initialize WebSocket
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-05-WebSockets-Start/README.md
Import the URLs configuration and establish a WebSocket connection to the demo URL.
```javascript
import { URLs } from '../../../tutorialsURLs.js'
const { WS_DEMO_URL } = URLs
//...
const ws = new WebSocket(WS_DEMO_URL)
```
--------------------------------
### Connect and Fetch Account List
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-4-Test-Request/README.md
This snippet shows how to connect to the API and set up an event listener to fetch and handle account data when a button is clicked. Ensure the 'connect' function is properly configured.
```javascript
const main = async () => {
connect({...})
const $accountListBtn = document.querySelector('#get-acct-btn')
$accountListBtn.addEventListener('click', async () => {
let accounts = await tvGet('/account/list')
handleAccountList(accounts)
})
}
```
--------------------------------
### Initial WebSocket Request
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-07-Making-Requests/README.md
This snippet demonstrates a basic click event listener that sends a 'product/find' request with 'ETH' as the query parameter to the WebSocket.
```javascript
$reqBtn.addEventListener('click', () => {
socket.send({
url: 'product/find',
query: 'name=ETH'
})
})
```
--------------------------------
### Initializing TradovateSocket in App
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-06-Heartbeats/README.md
Demonstrates how to import and instantiate the `TradovateSocket` class in the main application file (`app.js`) to manage WebSocket connections.
```javascript
import { TradovateSocket } from './TradovateSocket.js'
//...
const { accessToken } = await connect(credentials)
const ws = new TradovateSocket()
ws.connect(WS_DEMO_URL, accessToken)
```
--------------------------------
### Initialize Connect Function
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
This JavaScript code snippet shows the basic structure of the `connect.js` file, including importing URLs and exporting an empty `connect` function.
```javascript
import { URLs } from '../../../tutorialsURLs'
const { DEMO_URL } = URLs
export const connect = () => { /*...*/ }
```
--------------------------------
### Order Placement Parameters
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-4a-Place-An-Order/README.md
Defines the structure for placing an order, including required and optional parameters.
```json
{
accountSpec: "string",
accountId: 0,
clOrdId: "string",
action: "Buy", //required
symbol: "string", //required
orderQty: 0, //required
orderType: "Limit", //required
price: 0,
stopPrice: 0,
maxShow: 0,
pegDifference: 0,
timeInForce: "Day",
expireTime: "2019-08-24T14:15:22Z",
text: "string",
activationTime: "2019-08-24T14:15:22Z",
customTag50: "string",
isAutomated: true
}
```
--------------------------------
### Execute Connect Function
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
This snippet shows how to import and call the connect function to initiate the API request. Ensure the connect function is uncommented in app.js to run this.
```javascript
import { connect } from './connect'
connect()
```
--------------------------------
### WebSocket Connection and Subscription Logic
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-08-Realtime-Market-Data/README.md
This JavaScript code sets up a WebSocket connection, handles connection status updates, and manages subscriptions to real-time market data. It includes event listeners for user interactions like connecting, disconnecting, and requesting data.
```javascript
const main = async () => {
const { accessToken } = await connect(credentials)
//HTML elements
const $outlet = document.getElementById('outlet')
const $reqBtn = document.getElementById('request-btn')
const $unsubBtn = document.getElementById('unsubscribe-btn')
const $connBtn = document.getElementById('connect-btn')
const $discBtn = document.getElementById('disconnect-btn')
const $statusInd = document.getElementById('status')
const $symbol = document.getElementById('symbol')
//The websocket helper tool
const socket = new TradovateSocket()
let lastSymb
let unsubscribe
//give user some feedback about the state of their connection
//by adding an event listener to 'message' that will change the color
const onStateChange = _ => {
$statusInd.style.backgroundColor =
socket.ws.readyState == 0 ? 'gold' //pending
: socket.ws.readyState == 1 ? 'green' //OK
: socket.ws.readyState == 2 ? 'orange' //closing
: socket.ws.readyState == 3 ? 'red' //closed
: /*else*/ 'silver' //unknown/default
}
$connBtn.addEventListener('click', async () => {
if(socket.ws && socket.ws.readyState === 1) return
await socket.connect(URLs.MD_URL, accessToken)
//add your feedback function to the socket's
socket.ws.addEventListener('message', onStateChange)
})
//disconnect socket on disconnect button click
$discBtn.addEventListener('click', () => {
if(socket.ws.readyState !== 1) return
socket.ws.close()
$statusInd.style.backgroundColor = 'red'
$outlet.innerText = ''
})
$unsubBtn.addEventListener('click', () => {
unsubscribe()
lastSymb = ''
})
//clicking the request button will fire our request and initialize
//a listener to await the response. This will trigger our renders.
$reqBtn.addEventListener('click', async () => {
lastSymb = $symbol.value
unsubscribe = socket.subscribe({
url: 'md/subscribequote',
body: { symbol: $symbol.value },
subscription: data => {
const newElement = document.createElement('div')
newElement.innerHTML = renderQuote($symbol.value, data.entries)
$outlet.firstElementChild
? $outlet.firstElementChild.replaceWith(newElement)
: $outlet.append(newElement)
}
})
})
}
main()
```
--------------------------------
### Import URLs Configuration
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
Demonstrates how the `URLs` object is imported from a shared configuration file, typically used for API endpoints.
```javascript
import { URLs } from '../../../tutorialsURLs'
```
--------------------------------
### Subscribe to User Data and Calculate Open P&L
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-12-Calculating-Open-PL/README.md
Connects to the Tradovate API, subscribes to user data, and then subscribes to market data for each open position to calculate and display real-time P&L. Requires credentials and DOM elements like $openPL and $posList.
```javascript
const main = async () => {
const pls = []
//combines all your open p&ls into one
const runPL = () => {
const totalPL = pls.map(({pl}) => pl).reduce((a, b) => a + b, 0)
$openPL.innerHTML = ` $${totalPL.toFixed(2)}`
}
//Connect to the tradovate API by retrieving an access token
const { accessToken, userId } = await connect(credentials)
const socket = new TradovateSocket({debugLabel: 'Realtime API'})
await socket.connect(URLs.WS_DEMO_URL, accessToken)
const mdsocket = new TradovateSocket({debugLabel: 'Market Data API'})
await mdsocket.connect(URLs.MD_URL, accessToken)
socket.subscribe({
url: 'user/syncrequest',
body: { users: [userId] },
subscription: (item) => {
if(item.users) { //this is the initial response
const { positions, contracts, products } = item
positions.forEach(async pos => {
if(pos.netPos === 0 && pos.prevPos === 0) return
//we need the name variable from the contract this position is related to
const { name } = contracts.find(contract => contract.id === pos.contractId)
//get the value per point from products
let item = products.find(product => product.name.startsWith(name))
let vpp = item.valuePerPoint
//our subscription has an inner subscription
let unsubscribe = await mdsocket.subscribe({
url: 'md/subscribequote',
body: { symbol: name },
//entries is a field on the quote data object
subscription: ({entries}) => {
let buy = pos.netPrice ? pos.netPrice : pos.prevPrice
const { Trade } = entries //current Trade quote
const { price } = Trade //price of the Trade quote
let pl = (price - buy) * vpp * pos.netPos //our p&l formula
//render the HTML
const element = document.createElement('div')
element.innerHTML = renderPos(name, pl, pos.netPos)
const $maybeItem = document.querySelector(`#position-list li[data-name="${name}"`) // Corrected escaping for inner quotes
$maybeItem ? $maybeItem.innerHTML = renderPos(name, pl, pos.netPos) : $posList.appendChild(element)
//update existing p&l or push a new one
const maybePL = pls.find(p => p.name === name)
if(maybePL) {
maybePL.pl = pl
} else {
pls.push({ name, pl })
}
//run the p&l reducer to get total p&l
runPL()
}
})
})
}
}
})
//...
}
```
--------------------------------
### TradovateSocket Connect Method and Message Preparation
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-06-Heartbeats/README.md
Implements the `connect` method for establishing a WebSocket connection and handling the initial authorization message. The `prepareMessage` function is a utility for parsing incoming WebSocket data.
```javascript
TradovateSocket.prototype.connect = async function(url, token) {
console.log('connecting...')
const self = this
return new Promise((res, rej) => {
this.listeningURL = url
this.ws = new WebSocket(url)
//auth only
this.ws.addEventListener('message', function onConnect(msg) {
//we need 'self' to preserve outer 'this' value in event callbacks
const [T, _] = prepareMessage(msg.data)
if(T === 'o') {
self.send({
url: 'authorize',
body: token,
})
}
})
})
}
function prepareMessage(raw) {
const T = raw.slice(0, 1)
const data = raw.length > 1 ? JSON.parse(raw.slice(1)) : []
return [T, data]
}
```
--------------------------------
### Fetch and Render Product Data
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-07-Making-Requests/README.md
This snippet updates the click event listener to asynchronously fetch product data using the enhanced `socket.send` method and then renders the received data into a designated HTML element.
```javascript
$reqBtn.addEventListener('click', async () => {
let data = await socket.send({
url: 'product/find',
query: `name=ETH`
})
const div = document.createElement('div')
div.innerHTML = renderETH(data)
$outlet.firstElementChild
? $outlet.firstElementChild.replaceWith(div)
: $outlet.appendChild(div)
})
```
--------------------------------
### Subscribe to Real-Time Chart Data
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-11-Tick-Charts/README.md
This snippet demonstrates how to subscribe to real-time chart data, handling both tick and regular chart types. It includes logic for unsubscribing from previous subscriptions, setting chart parameters, and processing incoming data in the subscription callback. Use this when you need to display live chart updates.
```javascript
//...
$getChart.addEventListener('click', async () => {
all_bars = []
if(unsubscribe) unsubscribe() //unsubscribe existing subsciptions
if($type.value === 'Tick') {
_chart = getTickChart()
} else {
_chart = getRegularChart()
}
unsubscribe = await socket.subscribe({
url: 'md/getchart',
body: {
symbol: $symbol.value,
chartDescription: {
underlyingType: $type.value,
elementSize: $type.value === 'Tick' || $type.value === 'DailyBar' ? 1 : parseInt($elemSize.value),
elementSizeUnit: 'UnderlyingUnits',
// withHistogram: true,
},
timeRange: {
...{ asMuchAsElements: parseInt($nElements.value) },
// closestTimestamp: "2020-10-30T19:45:00.000Z",
asFarAsTimeStamp: "2020-05-01T19:45:00.000Z"
}
},
subscription: chart => {
console.log(chart)
// console.log($type.value)
if($type.value === 'Tick') {
handleTickChart(chart)
} else {
handleRegularChart(chart)
}
_chart.render()
}
})
})
//...
```
--------------------------------
### Initialize Data Array
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-10-Chart-Data/README.md
Declare an array to store the chart data points that will be fetched and processed.
```javascript
const main = async () => {
let all_bars = []
//...}
```
--------------------------------
### Subscribe to User Data Synchronization
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-07-Making-Requests/README.md
Connect to the WebSocket and subscribe to user data synchronization. This is essential for receiving real-time updates on account information. The callback function handles both the initial full data response and subsequent incremental updates.
```javascript
const main = async () => {
const { accessToken, userId } = await connect(credentials)
const socket = new TradovateSocket()
await socket.connect(WS_DEMO_URL, accessToken)
socket.subscribe({
url: 'user/syncrequest',
body: { users: [userId] },
subscription: item => {
if(item.users) {
//initial response has the `users` field and contains all of your current user data
const {
accountRiskStatuses,
accounts,
cashBalances,
commandReports,
commands,
contractGroups,
contractMaturities,
contracts,
currencies,
exchanges,
executionReports,
fillPairs,
fills,
marginSnapshots,
orderStrategies,
orderStrategyLinks,
orderStrategyTypes,
orderVersions,
orders,
positions,
products,
properties,
spreadDefinitions,
userAccountAutoLiqs,
userPlugins,
userProperties,
userReadStatuses,
users
} = item
//do setup stuff with data
} else {
//after initial response, subscription events look like this
const { entity, entityType, eventType } = item
}
}
})
}
```
--------------------------------
### Handle Fetch Response with .then()
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/Access/EX-0-Access-Start/README.md
This snippet demonstrates how to handle the data returned from a fetch request using the .then() method of a Promise. It logs the received data to the console.
```javascript
const connect = () => {
fetch(DEMO_URL + '/auth/accesstokenrequest')
.then(data => console.log(data))
}
```
--------------------------------
### Render ETH Product Data
Source: https://github.com/tradovate/example-api-js/blob/main/tutorial/WebSockets/EX-07-Making-Requests/README.md
A JavaScript function to generate HTML for displaying product details. It takes a product object and returns an HTML string.
```javascript
export const renderETH = ({
allowProviderContractInfo,
contractGroupId,
currencyId,
description,
exchangeChannelId,
exchangeId,
id,
isMicro,
marketDataSource,
name,
priceFormat,
priceFormatType,
productType,
status,
tickSize,
valuePerPoint,
}) => {
return `
currency ID: ${currencyId == 1 ? '$' : currencyId} ${description}${name}
info:
Description