If you are a freelancer or CTO of a financial project, sooner or later you will be faced with the issue of connecting charts, I will save you at least a day of work. Those who are already using this library may find something new.
The article will be in the format of a “recipe book” with open source solutions for the Binance and Forex cryptocurrency exchanges.
Hello, Habr!
The TradingView library (charting_library) has a high entry threshold, but it has not become less popular due to the fact that it is used on the TradingView.com service of the same name. I decided to make a “recipe book” with answers to basic questions.
This article is a continuation of the post: “Financial charts for your application.”
English version.
I will add content as new difficulties arise. If you have questions and did not find answers in the article, write in the comments, we will figure it out together
In the article I will provide links to documentation. If, when you click on a link, you get a 404 page , this means that you do not have access.
License
Free to use for commercial and non-commercial purposes. The most important criterion is the preservation of the company logo on the charts.
When requesting access to graphs, be sure to specify the destination domain where they will be used. When implementing one of the projects, we connected the Forex date to the chart, set everything up and launched it. For the 2nd month, the customer did not pay for Forex data, because of this, the charts did not load completely and the logo was missing. After this situation, the inspector contacted the customer via email with questions to clarify the situation.
The bottom panel
And the last thing that interests us is the bottom menu. Something new is constantly being added to it. Now it contains:
- Notebook.
- Script editor.
- Trading panel.
- Strategy tester.
- Screenshot tool.
- Sharing on twitter or stocktwits.
- Publish ideas button.
- Complaint button about data inconsistency.
Notepad (Text Notes)
A simple text notepad where you can write down your thoughts.
Script Editor (Pine Editor)
All indicator scripts written by traders themselves are created in a scripting language called Pine.
The easiest way to understand how it works is to simply look at the source code of other scripts. There are two sources you can use to study Pine:
- official Pine tutorial;
- Pine Variables Manual.
I also wrote a few simple indicators for myself. Let's say here is the indicator code that shows the maximum and minimum price for the day, compared to the previous day. Used on TF for less than 1 day. //binguru.net highest and lowest prices of the day compared with the previous D study(title=”HHLL”, shorttitle=”HL”, overlay=true) dd = security(tickerid, 'D', high) ddd = security (tickerid, 'D', high[1]) ll = security(tickerid, 'D', low) lll = security(tickerid, 'D', low[1]) isHigh() => high > ddd and high = = dd isLow() => low < lll and low == ll barcolor(isHigh() ? #43FF00 : isLow() ? #F9F104 : na) plotchar(isHigh(), char='H') plotchar(isLow() , char='L', location = location.belowbar) It looks like this on the chart:
Trading Panel
This is the same as a demo account in MetaTrader. Demo Forex. You are given $100,000 to balance and then you practice buying and selling.
I am sure that over time Tradingview will implement the possibility of real trading directly on their platform (move your ass or something, I’m really looking forward to it). Apparently, this demo version is a preparation of the platform for just such trading.
Reading the reviews, it becomes clear that some guys don’t know where to hide the Sell/Buy panel and always put it somewhere else. Click on the gear and just uncheck/check the Show Buy/Sell Panel box and it won’t bother you.
In the same menu you can return your honestly lost demo money (Reset Paper Trading Account), there is a transaction diary (Journal), properties, etc.
Well, demo trading itself is as simple as a slipper. Click Sell or Buy and enter the parameters of your transaction. Everything here is the same as in Forex and in MetaTrader.
- Market menu (market order): lot volume, take profit and stop loss values.
- Limit and Stop menu (pending order): these are the parameters of the buy limit/buy stop and sell limit/sell stop orders.
More information about the types of limit orders can be found in the MetaTrader help.
4. Strategy Tester
The article took so long to write that TV managed to add new functionality - a strategy tester.
To use it, you need to select Strategies in the Indicators and Strategies menu.
The tester is used primarily for Forex. When you select a strategy in the Strategy Tester menu, a list of transactions made on history appears according to the rules specified in the strategy script.
Let's say we select Bollinger Bands Strategy. List of entries made by the script on history:
The source code of the script can be viewed by clicking on any of the buttons:
Well, the chart will clearly show the entries into and exits from the transaction.
The source code allows you to both change the strategy itself and write it from scratch in the Pine scripting language.
Screenshots
Incredibly convenient and most frequently used function. Click on the camera icon and receive a link to a screenshot of your chart.
No need to mess around with third-party programs, everything is already built-in.
Sharing
A link to a screenshot of your chart can be published in two services: Twitter and StockTwits.
StockTwits is a fun service, I recommend taking the time to get to know it. Sometimes even useful.
Post ideas button
Everything is simple here. We have already talked about ideas, all that remains is to choose for whom to publish them:
- Publish Idea – for everyone;
- Publish Private Idea – just for you.
The idea will be indicated with a special icon directly on the chart.
Complaint button
The button in the form of a bug allows you to complain, but only about incorrect display of prices, freezing of the chart and problems with quotes. There is no need to write questions like “how can I draw a trend line” here, don’t anger the developers.
This concludes the review of Tradingview capabilities. As usual, no one reads such articles in full, so in the end I can write whatever I want, say, how I got naughty with two blondes. Or three. I don't remember, I was drunk, sorry.
The graph is not displayed, even with test data
To solve this, you need to connect the widget and globally specify access to the library.
Widget connection
// for Nodejs import { widget } from '../public/charting_library/charting_library.min' const widget = new widget({ })
Library access
Specify the global path to the charting_library in the library_path widget options: '/charting_library/'
The global path will differ depending on the modules used. In my case, Vuejs is used with vue.config.js => publicPath: '/' specified. Folder structure: /public/index.html, /public/charting_library/ and widget settings as listed above.
Documentation
Volume Trend Meter
A nice little indicator that measures volumetric pressure over a period of time. I call it Volume Trend Meter or simply VTM. The indicator sums up the volumes of all green and red candles for a certain period of bars (which you set in the settings) and plots their values. Use this indicator to identify increasing volume with green candles (close above the open) and increasing volume with red candles (close below the open).
How the indicator is calculated
For the green column: the total volume of green candles is greater than the total volume of red candles. For the red column: the total volume of red candles is greater than the total volume of green candles.
Volume Trend Meter Colors
Green: increasing buying pressure. Red: increasing selling pressure.
Add to platform. https://ru.tradingview.com/script/ywEEvEtI-Volume-Trend-Meter/
Data connection
The basic version uses test data. Next, you need to connect your data provider using one of two solutions: JS API or UDF . It is not possible to directly “feed” a data array. We will look at JSAPI; UDF is connected in a similar way, with the difference in specifying the endpoint on the server from where it will receive data.
- JS API - client side connection
- UDF - connection on the server side
The main difference between JSAPI and UDF is that UDF does not have the ability to add a WebSocket connection. When specifying an endpoint on the server, you set the interval for each request: datafeed: new Datafeeds.UDFCompatibleDatafeed('https://localhost:3000/datafeed', 1000)
Documentation
TradingView JS API adapter
To configure the adapter, you need to understand that each hook is executed sequentially and for debugging it is better to add output to the console about the launch of the hook console.log('[<hook name>]: Method call').
Launch sequence: onReady => resolveSymbol => getBars => subscribeBars => unsubscribeBars .
If you change the timeframe, symbol, the unsubscribeBars , which calls your function, which resets the WebSocket connection to the data provider. If you don't use subscribeBars , then you don't need unsubscribeBars The getServerTime hook is optional, but if you need to use server time, include it.
If the data provider does not provide volumes, you can specify resolveSymbol — has_no_volume: true .
export default { // Initialization of settings, must be given ASYNCHRONOUSLY onReady: (callback) => { console.log('[onReady]: Method call'); // setTimeout(() => callback(<
When the data provider does not allow you to request data directly from the client, for example the Binance exchange, so the request can be sent through a proxy.
JS API Documentation | Working example
TradingView UDF adapter
The UDF adapter is relevant when data is requested from its server. In the client constructor you need to specify datafeed: new Datafeeds.UDFCompatibleDatafeed('https://localhost:3000/datafeed', 1000)
// example of a plugin design for **Fastify** // main.js const app = Fastify() app.register(import('./modules/tradingview'), {}) // tradingview.js const plugin = async ( app, options) => { // check the endpoint is working app.get('/', (req, res) => { res.code(200).header('Content-Type', 'text/plain') .send('Welcome to UDF Adapter for TradingView. See ./config for more details.') }) // server time app.get('/time', (req, res) => { console.log('[ time]: Method call') const time = Math.floor(Date.now() / 1000) // In seconds res.code(200).header('Content-Type', 'text/plain').send( time.toString()) }) // analogue of onReady // https://github.com/tradingview/charting_library/wiki/UDF#data-feed-configuration-data app.get('/config', (req, res ) => { console.log('[config]: Method call') }) // called if: supports_group_request: true & supports_search: false app.get('/symbol_info', async (req, res) => { console .log('[symbol_info]: Method call') }) // called if: supports_group_request: false & supports_search: true app.get('/symbols', async (req, res) => { console.log('[ symbol_info]: Method call') const symbol = await getSymbols(req.query.symbol) return symbol }) // analogous to getBars, requests historical data app.get('/history', async (req, res) => { console .log('[history]: Method call') }) }
UDF Documentation
Reviews about TradingView
The Tradingview web platform serves as a convenient tool for traders from all over the world. And after reading the reviews, we can conclude that most users are satisfied with the functionality of the service (a variety of tools for working with charts, many additional functions, a social network, etc.).
On Trustpilot, in the section about TradingView, there are negative reviews that are not related to the operation of the platform: people simply complain that they receive calls from scammers who ask to transfer money to them. It’s just not entirely clear what tradingview has to do with it. In any case, filter the information received from different sources.
The limitations in the free version are not critical for beginners, and a wide range of subscription tools serves as a good assistant for experienced investors in everyday trading.
In any case, start with the trial version, test all the tools, and decide whether to continue using TradingView. ✅
JS API getBars hook is called many times
This happens when there is not enough data and the library independently tries to “upload” the information. getBars hook has a firstDataRequest that returns a boolean value true\false, use it. Returns true only when the market is loaded.
getBars: (symbolInfo, interval, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) => { console.log('[getBars] Method call', symbolInfo, interval) console.log('[getBars] First request', firstDataRequest) if (firstDataRequest) { console.log('do something') } },
What is it and why
The software project of immigrants from Russia is an exchange information Web service and a social network for traders, analysts, and investors, implemented on the basis of an online platform for conventional technical analysis. The first version of TradingView was released in September 2011 and already in May 2017 it was recognized as the best analytical platform according to the Benzinga Global Fintech Awards (more details for the curious, link to Wikipedia).
The headquarters of the TradingView service operates in New York, the European office is in London, and the development teams are in Rostov, St. Petersburg and Moscow.
TradingView receives and processes stock information in tick-by-tick mode. The service “collects” a stream of quotes from almost all exchanges, including stock and commodity exchanges. cryptocurrency, as well as large brokers, and presents them to the user in the form of price charts (charts) with many additional functions. Access is guaranteed from any device without installing any software.
The TradingView online platform offers all modern – standard and original – tools for market analysis, creating and testing trading ideas, as well as ready-made forecasts, analytics, trading signals, and free communication. Everything that every trader needs is collected on one platform; just open the service website in any browser.
The project is aimed at private investors and regularly attracts venture capital investments for its development. The interface is offered in 18 languages, the Russian version is here.
Register an account with the broker RoboForex
My ISP does not have WebSocket connections
It is not necessary to use a UDF provider if there is no stream. It is not possible to set the request interval for the JS API adapter, but this does not prevent us from adding setInterval to subscribeBars and sending data for updating.
subscribeBars: (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => { console.log('[subscribeBars]: Method call with subscribeUID:', subscribeUID) window.interval = setInterval(function () { getLastKline(symbolInfo.ticker, resolution).then(kline => onRealtimeCallback(kline)) }, 1000 * 60) // 60s update interval }, unsubscribeBars: (subscriberUID) => { console.log('[unsubscribeBars]: Method call with subscriberUID:', subscriberUID) clearInterval(window.interval) console.log('[unsubscribeBars]: cleared') }
Working example
Cumulative Volume Delta
The total delta volume is one of the key analyzes when determining the relationship between volume and price. The application is very easy to understand.
The image below shows how this is calculated:
Add to platform. https://ru.tradingview.com/script/lsDHdn0H-Cumulative-Volume-Delta/
Design customization
By default, two themes are available: theme: “Light” || "Dark". You can also use your own color schemes. Over time, you will encounter a problem when the colors have changed everywhere except the header_widget (the top block with the search, compare, etc. buttons), it needs to be changed through .css .
In the widget options you need to specify: custom_css_url: '/tradingview.css', where / is the absolute path from your index.html. With content:
.chart-controls-bar { border-top: none !important; } .chart-page, .group-wWM3zP_M- { background: transparent !important; } .pane-separator { display: none !important; }
Documentation
Synthetic instruments
One of the most attractive strategies on the market is arbitrage. The TradingView platform allows you to build complex spread charts from groups of correlated instruments.
To do this, you need to enter the first character in the upper left corner, then a space, a multiplication or division sign, a space and the second character.
For example, if you enter AAPL / XAUUSD
Then we get a comparison of Apple stock prices and gold by dividing stock prices by gold prices. We will find out how much 1 share costs in ounces of gold.
For example, let's try to plot the spread of Brent oil against the dollar/ruble pair. To do this, multiply oil by dollar/ruble:
As you can see, the instruments are highly dependent. As soon as the ruble begins to depreciate, oil immediately comes to the rescue (or vice versa). The main idea of the strategy is to trade up from the lower edge of the channel, and down from the top.
Another example is the pair USDCHF and EURUSD, the dependence of which is also quite strong, although not constant. The result of their interaction can also be observed in the cross-rate. When the spread diverges, the EURCHF pair shows a trend. Accordingly, when the pair is in the overbought zone, we sell the spread, and when it becomes significantly cheaper, we buy. You can buy a spread with a contract to buy the EURCHF pair, or sell it with a contract to sell EURCHF.
Saving data
You may need to save the “drawing sketches”.
Save\Load methods
The simplest option that can be used if you do not plan to draw a lot on the charts. Simple because you can call the object with all the chart data widget.save(cb => this.setOverlay(cb)) and save it wherever it is convenient.
Working example
Save\Load adapter
Similar to UDF adapter. On the server, raise endpoints for saving/loading data.
Documentation
Left panel
We've sorted out the top panel, let's look at the panel on the left.
There are 17 elements in total. Don't be alarmed, everything is simple.
- Cursor type (cross, dot or arrow).
- The main tools of technical analysis are lines. Trends, vertical, horizontal, rays, channels, etc.
- Advanced graphical tools - from forks and Gann boxes to Fibonacci tools.
- Ability to draw any shapes and graphic shapes like triangles, rectangles, etc.
- Text elements and arrows.
- Patterns – head and shoulders, triangles, Elliott waves, cyclic lines.
- Tools for forecasting and calculating risks.
- A bunch of different icons.
- Possibility to enlarge the selected fragment.
- Obtaining accurate data on the selected fragment.
- Magnet mode.
- Drawing mode.
- Locks all drawing tools.
- Hide everything drawn on the chart (and return it back).
- Synchronization of drawings for all graphs.
- Tree of objects on the chart.
- Removing all graphic elements from the chart.
Let's consider only some of the elements, because most of them are intuitive and do not require description.
Basic graphical tools of technical analysis
This is the menu you will use most often. Use it to draw:
- Trend Line;
- support/resistance lines (Horizontal Line);
- channels (Parallel Channel).
and their various varieties (beams, modified channels, etc.) The most basic elements that you should already know by studying the article Technical Analysis .
Forks, Gann, Fibonacci
Many beginners suffer from Fibonacci, this menu is for them.
The first are the so-called Pitchforks, including the Schiff Pitchfork. Trader Jeremy Schiff has developed his own unique method of technical analysis based on the use of such forks.
Next are various tools from William Gann - don't mess with them, seriously. Gunn will give you a headache.
Well, then there are various types of Fibonacci graphical tools. The most popular is a simple grid.
To stretch the Fibonacci retracement, select Fib Retracement:
And we pull the grid:
There are other tools there, various spirals and so on. Those who are interested in Phoebe will have the cards in their hands.
Risk forecasting and calculation tools
A very important menu containing the tools you need to analyze your trading risks.
Forcast
A popular tool is Forecast. With its help, you can learn to make normal forecasts without losing money to the broker.
The forcast extends from the last candle to where you think the price will be.
We set a forecast and are free. When you return, it will show whether the forecast was successful (green Success) or not (red Failure).
The blue forcast menu displays the price change in points, as a percentage, and the forecast period.
Another tool is required for use in Forex and allows you to calculate the risk/loss ratio (P&L - Profit & Loss) for using stop losses and take profits. And also the Risk/Reward ratio (profit/risk).
Instruments are selected depending on the direction of price movement.
- Long Positions – for an upward trend.
- Short Position – for a downward trend.
All other menus are clear from their names and you yourself will figure out what’s what.
Something doesn’t work for me, I’m doing everything according to the documentation
A real case, a freelancer approached me with a project, the project was old, he was rewriting it. As a result, there was simply an old version of the library. Check the version.
Another situation is when they try to call methods on a chart that is not yet loaded, monitor the state via onChartReady . If there is no reactivity under the hood to track the loading of the graph, use the Observer .
widget.onChartReady(function() { // It's now safe to call any other methods of the widget });
Simple VSA
There isn't much discussion about VSA right now, although it is a very good method for analyzing markets.
This indicator attempts to display simple Volume Spread Analysis (VSA) concepts as they appear in real time. These concepts have been borrowed from various VSA experts and applied through this simple script. The code logic is done by me after learning and testing these VSA concepts.
The Simple VSA indicator is not intended to work independently, it is just an auxiliary tool. Trading remains discretionary. It does a good job of recognizing many VSA signals, but of course misses some or shows some false ones. The trader must decide how he will trade around it. To use this indicator, you must know VSA in advance.
Signals are based on: high volume action including tight and wide spreads (orange/blue signals) low volume action such as no supply and no demand (purple signals) price action such as springs, upthrust and two-bar reversal ( red / green) spread of columns in relation to volume and closure, for example, effort to result
Other features: SMA based medium term trend system with level bar colors and color bars for up and down bars
Add to platform. https://ru.tradingview.com/script/xBk0Cv4P-Simple-VSA/
How to add orders to a chart
After adding an order to the chart, there is no access to the array, so you need to track the orders yourself. I’ll share my solution, formatted as a mixin for Vuejs, the essence will be clear.
import orders from '../../../multiblock/orders/mixin' import createOrder from './createOrder' import openOrders from './openOrders' import trades from './trades' export default { mixins: [orders , createOrder, openOrders, trades], data: () => ({ lines: new Map() }), watch: { onChartReady(val) { if (val) { //* Uncomment: Testing price line // this. line({ id: 'test', price: 0.021, quantity: 100 }) } }, }, methods: { // Line: open orders positionLine(data) { this.line(data) .onCancel(() => { this.deleteLine(data.id) this.$bus.$emit('market-orders-deleteOrder', data.id) }) .onMove(() => this.$bus.$emit('market-orders -updateOrder', { id: data.id, price: this.lines.get(data.id).getPrice() })) }, // Line: order mobule ('price', 'stopPrice') orderLine({ id = 'price', …data }) { this.line({ id, …data }) .onMove(() => { // Set new value on dragging this.$store.commit('setMarketOrder', { [ id]: this.lines.get(id).getPrice() }) }) .onCancel(() => { // Delete price line & set price = 0 this.deleteLine(id) this.$store.commit( 'setMarketOrder', { [id]: 0 }) // set 0 value in vuex storage }) }, line({ id = 'price', text = 'Price', color = '#ff9f0a', price, quantity, fontColor = '#fff', lineStyle = 2, lineLength = 25 }) { if (this.lines.has(id)) this.deleteLine(id) // Creating line from scratch const widget = this.widget.chart() .createOrderLine() .setText(text) .setPrice(price) .setQuantity(quantity) .onModify(res => res) // Need for dragging // Customize color .setLineColor(color) .setBodyTextColor(fontColor) .setBodyBorderColor(color ).setBodyBackgroundColor(color) .setQuantityBorderColor(color) .setQuantityTextColor(fontColor) .setQuantityBackgroundColor(color) .setCancelButtonBorderColor(color) .setCancelButtonBackgroundColor(color) .setCancelButtonIconColor(fontColor) .setLineLength(lineLength) // Margin right 25 % .setLineStyle( lineStyle) this.lines.set(id, widget) return widget // return for orderLine func() }, deleteLine(id) { this.lines.get(id).remove() this.lines.delete(id) } , deleteLines() { this.lines.forEach((value, key) => this.deleteLine(key)) } } }
Documentation