Core trading concepts
Trading Platform provides the ability to trade right from the chart. Users can manage orders, track positions, monitor their potential profits and losses, and more. In this article, you will learn about the trading components, how they integrate into the chart widget, and how they work together.
Components
Trading in Trading Platform is based on two key components: the Broker API and the Trading Host. The diagram below illustrates how these components should be integrated with the library and your backend server.
The Backend trading server and Broker API are the parts that you should implement.
Broker API
The Broker API is a component that enables trading. Its purpose is to connect TradingView charts with your trading logic. In JavaScript terms, the Broker API is an object that implements a particular interface.
You can implement the Broker API in two ways:
- with real-time updates through the
IBrokerTerminal
interface - without real-time updates through the
IBrokerWithoutRealtime
interface
If you are not sure what type of updates you want to provide,
you can start by implementing the IBrokerWithoutRealtime
interface.
Trading Host
The Trading Host is an API for interaction between the Broker API and the trading-related library code. Its purpose is to receive information from your backend server where the trading logic is implemented and provide updates to the library.
The Trading Host is described by the IBrokerConnectionAdapterHost
interface.
You should call the Trading Host methods from your Broker API implementation.
Connecting trading
To enable trading, you should pass the function that returns a new object of the Broker API implementation to the library.
To do this, use the broker_factory
property of the Trading Platform Widget Constructor.
Note that this function should accept the Trading Host instance as a parameter.
In the code sample below, the function assigned to broker_factory
returns BrokerSample
that implements IBrokerWithoutRealtime
.
const datafeed = new Datafeeds.UDFCompatibleDatafeed("https://demo-feed-data.tradingview.com");
new TradingView.widget({
container: "chartContainer",
locale: "en",
library_path: "charting_library/",
datafeed: datafeed,
symbol: "AAPL",
interval: "1D",
broker_factory: function(host) { return new Brokers.BrokerSample(host, datafeed); },
})
Trading features configuration
You can configure trading features using the broker_config
property of the Trading Platform Widget Constructor.
This property is primarily used to specify the configFlags
object, which contains a list of configuration flags.
Some flags only enable or disable trading elements in the UI,
while others activate more advanced features that require corresponding methods to be implemented in the Broker API.
Consider the Widget Constructor with the following properties.
const datafeed = new Datafeeds.UDFCompatibleDatafeed("https://demo-feed-data.tradingview.com");
new TradingView.widget({
container: "chartContainer",
locale: "en",
library_path: "charting_library/",
datafeed: datafeed,
symbol: "AAPL",
interval: "1D",
broker_factory: function(host) { return new Brokers.BrokerSample(host, datafeed); },
broker_config: {
configFlags: {
supportEditAmount: false,
supportLeverage: true,
},
},
})
In this code sample, the supportEditAmount
flag disables the control of order quantity in the Order Ticket when users modify orders.
This flag only affects the UI.
The supportLeverage
flag enables trading with leverage.
However, you should also implement the leverageInfo
method to provide the library with leverage calculations.
How library gets user's data
When the chart is initially loaded, the library requests data from your Broker API implementation through the following methods:
orders
positions
executions
individualPositions
(optional, required if thesupportPositionNetting
flag is set totrue
).
Using these methods, the library retrieves data about the orders, positions, and executions the user already had before the chart creation. Then, the library gets updates for these orders and positions through the Trading Host methods. Refer to the next section for a step-by-step example.
How components work together
To understand how the library, Broker API, Trading Host, and your implemented trading logic should work together, consider the following step-by-step example. Suppose a user wants to buy 10 AAPL shares. This user action initiates three consecutive steps:
In the subsequent sections, you will delve into each of these steps, finding detailed explanations and sequence diagrams:
You can also refer to the diagram that illustrates the entire process, starting from creating the order in the UI until the position is established.
1. Order creation
The diagram below illustrates the process of creating an order.
- The user specifies 10 units of AAPL shares in the Order Ticket and clicks the Buy button.
- The library interprets this action as a trigger to notify your Broker API implementation that the user wants to create the order.
- The library calls the
placeOrder
method, passing along the order data. The code sample below shows an example of the data object:Note that your Broker API implementation should interpret this call as a notification of the user's intent to create the order.{
"symbol": "NasdaqNM:AAPL",
"type": 2, // OrderType.Market
"side": 1, // Side.Buy
"qty": 10,
"currentQuotes": {
"ask": 173.68,
"bid": 173.68
},
"customFields": {}
} - Your Broker API implementation responds with
PlaceOrderResult
, which should include anorderId
. - The library waits for your backend server to create the order within 10 seconds and provide the updated information. Note that the library will return a timeout issue if it fails to receive a timely order update.
- Your Broker API implementation requests your backend server to create the order.
- Your backend server creates the order and prepares the updated information.
- Your backend server provides a response to your Broker API implementation with updated information.
- Your Broker API implementation calls the
orderUpdate
method. As a parameter, it sends thePlacedOrder
object to the library. Note that theqty
,id
,symbol
, andside
properties must be identical to the data provided in step 3 within theplaceOrder
method.
The code sample below shows an example of thePlacedOrder
object:{
"id": "1",
"qty": 10,
"side": 1, // Side.Buy
"status": 6, // OrderStatus.Working
"symbol": "NasdaqNM:AAPL",
"type": 2 // OrderType.Market
} - The Trading Host receives updates and informs the library and the UI that the order has been created.
- The user sees the new working order in the Account Manager.
After this, the backend server should execute the working order and add a new position.
2. Execution update
At this point, the user can see the new working order in the Account Manager. Following this, your backend server is responsible for executing the order and creating a position. The diagram below illustrates this process.
- Your backend server executes the order and prepares the updated information. Note that the order execution and update might be processed on external sources, such as exchanges. However, your server is expected to manage this information and provide it in the format required by the library.
- Your backend server provides a response to your Broker API implementation with updated information.
- Your Broker API implementation calls the
executionUpdate
method. As a parameter, it sends theExecution
object. The code sample below shows an example of this object:{
"price": 173.68,
"qty": 10,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"time": 1697032262341
} - Your Broker API implementation calls the
orderUpdate
method to update the order status to filled. As a parameter, your Broker API implementation sends thePlacedOrder
object. The code sample below shows an example of this object:{
"id": "1",
"qty": 10,
"side": 1, // Side.Buy
"status": 2, // OrderStatus.Filled
"symbol": "NasdaqNM:AAPL",
"type": 2, // OrderType.Market
} - Your Broker API implementation calls the
positionUpdate
method to notify the Trading Host that the position is added. As a parameter, it sends thePosition
object. The code sample below shows an example of this object:{
"id": "NasdaqNM:AAPL",
"qty": 10,
"side": 1, // Side.Buy
"symbol": "NasdaqNM:AAPL",
"avgPrice": 173.68
} - The Trading Host receives updates and informs the library and the UI that the order has been executed and the position has been added.
- The user sees a new position of 10 AAPL shares in the Account Manager.
After this, your backend server should update user's equity.
3. Equity update
At this stage, the user sees that the order has been executed and the position has been created. Next, your backend server should update the user's equity and the Profit & Loss (P&L) values for all active positions whenever there is a price change.
To keep the UI data up-to-date, you should constantly provide updates of users' entity and P&L values whenever changes occur.
The diagram below illustrates the process of updating the equity and P&L values.
- Your backend server calculates the user's equity and P&L and prepares the updated information. Note that the calculations might be processed on external sources, such as exchanges. However, your server is expected to manage this information and provide it in the format required by the library.
- Your backend server provides a response to your Broker API implementation with updated information.
- Your Broker API implementation calls the
equityUpdate
method to notify the Trading Host about equity updates. As a parameter, it sends the accurate equity amount, for example,[10000000]
. - Your Broker API implementation calls the
plUpdate
method to notify the Trading Host about P&L updates. - The Trading Host notifies the library and the UI about updates.
- The user sees updated equity and P&L values in the Account Manager.
At this stage, the user owns the position of 10 AAPL shares.
Implementation example
You can check the sample code of the Broker API implementation 🔐 (access is restricted) on GitHub. This example is used on the Trading Platform demo page where you can play around with trading features.