@@ -8,11 +8,15 @@ const validateStatus = (status) => status < 500;
88const indicators = [ 'Recommend.Other' , 'Recommend.All' , 'Recommend.MA' ] ;
99const builtInIndicList = [ ] ;
1010
11- async function fetchScanData ( tickers = [ ] , type = '' , columns = [ ] ) {
12- const { data } = await axios . post ( `https://scanner.tradingview.com/${ type } /scan` , {
13- symbols : { tickers } ,
14- columns,
15- } , { validateStatus } ) ;
11+ async function fetchScanData ( tickers = [ ] , columns = [ ] ) {
12+ const { data } = await axios . post (
13+ 'https://scanner.tradingview.com/global/scan' ,
14+ {
15+ symbols : { tickers } ,
16+ columns,
17+ } ,
18+ { validateStatus } ,
19+ ) ;
1620
1721 return data ;
1822}
@@ -40,56 +44,21 @@ async function fetchScanData(tickers = [], type = '', columns = []) {
4044 * }} Periods
4145 */
4246
43- // /**
44- // * @typedef {string | 'forex' | 'crypto'
45- // * | 'america' | 'australia' | 'canada' | 'egypt'
46- // * | 'germany' | 'india' | 'israel' | 'italy'
47- // * | 'luxembourg' | 'poland' | 'sweden' | 'turkey'
48- // * | 'uk' | 'vietnam' } Screener
49- // * You can use `getScreener(exchange)` function for non-forex and non-crypto markets.
50- // */
51-
5247module . exports = {
53- // /**
54- // * Get a screener from an exchange
55- // * @function getScreener
56- // * @param {string } exchange Example: BINANCE, EURONEXT, NASDAQ
57- // * @returns {Screener }
58- // */
59- // getScreener(exchange) {
60- // const e = exchange.toUpperCase();
61- // if (['NASDAQ', 'NYSE', 'NYSE ARCA', 'OTC'].includes(e)) return 'america';
62- // if (['ASX'].includes(e)) return 'australia';
63- // if (['TSX', 'TSXV', 'CSE', 'NEO'].includes(e)) return 'canada';
64- // if (['EGX'].includes(e)) return 'egypt';
65- // if (['FWB', 'SWB', 'XETR'].includes(e)) return 'germany';
66- // if (['BSE', 'NSE'].includes(e)) return 'india';
67- // if (['TASE'].includes(e)) return 'israel';
68- // if (['MIL', 'MILSEDEX'].includes(e)) return 'italy';
69- // if (['LUXSE'].includes(e)) return 'luxembourg';
70- // if (['NEWCONNECT'].includes(e)) return 'poland';
71- // if (['NGM'].includes(e)) return 'sweden';
72- // if (['BIST'].includes(e)) return 'turkey';
73- // if (['LSE', 'LSIN'].includes(e)) return 'uk';
74- // if (['HNX'].includes(e)) return 'vietnam';
75- // return 'global';
76- // },
77-
7848 /**
7949 * Get technical analysis
8050 * @function getTA
81- * @param {Screener } screener Market screener
8251 * @param {string } id Full market id (Example: COINBASE:BTCEUR)
8352 * @returns {Promise<Periods> } results
8453 */
85- async getTA ( screener , id ) {
54+ async getTA ( id ) {
8655 const advice = { } ;
8756
8857 const cols = [ '1' , '5' , '15' , '60' , '240' , '1D' , '1W' , '1M' ]
8958 . map ( ( t ) => indicators . map ( ( i ) => ( t !== '1D' ? `${ i } |${ t } ` : i ) ) )
9059 . flat ( ) ;
9160
92- const rs = await fetchScanData ( [ id ] , screener , cols ) ;
61+ const rs = await fetchScanData ( [ id ] , cols ) ;
9362 if ( ! rs . data || ! rs . data [ 0 ] ) return false ;
9463
9564 rs . data [ 0 ] . d . forEach ( ( val , i ) => {
@@ -107,53 +76,99 @@ module.exports = {
10776 * @prop {string } id Market full symbol
10877 * @prop {string } exchange Market exchange name
10978 * @prop {string } fullExchange Market exchange full name
110- * @prop {Screener | 'forex' | 'crypto' } screener Market screener
11179 * @prop {string } symbol Market symbol
11280 * @prop {string } description Market name
11381 * @prop {string } type Market type
11482 * @prop {() => Promise<Periods> } getTA Get market technical analysis
11583 */
11684
11785 /**
118- * Find a symbol
86+ * Find a symbol (deprecated)
11987 * @function searchMarket
12088 * @param {string } search Keywords
12189 * @param {'stock'
12290 * | 'futures' | 'forex' | 'cfd'
12391 * | 'crypto' | 'index' | 'economic'
12492 * } [filter] Caterogy filter
12593 * @returns {Promise<SearchMarketResult[]> } Search results
94+ * @deprecated Use searchMarketV3 instead
12695 */
12796 async searchMarket ( search , filter = '' ) {
12897 const { data } = await axios . get (
129- ` https://symbol-search.tradingview.com/symbol_search/?text= ${ search . replace ( / / g , '%20' ) } &type= ${ filter } ` ,
98+ ' https://symbol-search.tradingview.com/symbol_search' ,
13099 {
131- validateStatus,
100+ params : {
101+ text : search . replace ( / / g, '%20' ) ,
102+ type : filter ,
103+ } ,
132104 headers : {
133105 origin : 'https://www.tradingview.com' ,
134106 } ,
107+ validateStatus,
135108 } ,
136109 ) ;
137110
138111 return data . map ( ( s ) => {
139112 const exchange = s . exchange . split ( ' ' ) [ 0 ] ;
140113 const id = `${ exchange } :${ s . symbol } ` ;
141114
142- // const screener = (['forex', 'crypto'].includes(s.type)
143- // ? s.type
144- // : this.getScreener(exchange)
145- // );
146- const screener = 'global' ;
115+ return {
116+ id,
117+ exchange,
118+ fullExchange : s . exchange ,
119+ symbol : s . symbol ,
120+ description : s . description ,
121+ type : s . type ,
122+ getTA : ( ) => this . getTA ( id ) ,
123+ } ;
124+ } ) ;
125+ } ,
126+
127+ /**
128+ * Find a symbol
129+ * @function searchMarketV3
130+ * @param {string } search Keywords
131+ * @param {'stock'
132+ * | 'futures' | 'forex' | 'cfd'
133+ * | 'crypto' | 'index' | 'economic'
134+ * } [filter] Caterogy filter
135+ * @returns {Promise<SearchMarketResult[]> } Search results
136+ */
137+ async searchMarketV3 ( search , filter = '' ) {
138+ const splittedSearch = search . toUpperCase ( ) . replace ( / / g, '+' ) . split ( ':' ) ;
139+
140+ const request = await axios . get (
141+ 'https://symbol-search.tradingview.com/symbol_search/v3' ,
142+ {
143+ params : {
144+ exchange : ( splittedSearch . length === 2
145+ ? splittedSearch [ 0 ]
146+ : undefined
147+ ) ,
148+ text : splittedSearch . pop ( ) ,
149+ search_type : filter ,
150+ } ,
151+ headers : {
152+ origin : 'https://www.tradingview.com' ,
153+ } ,
154+ validateStatus,
155+ } ,
156+ ) ;
157+
158+ const { data } = request ;
159+
160+ return data . symbols . map ( ( s ) => {
161+ const exchange = s . exchange . split ( ' ' ) [ 0 ] ;
162+ const id = `${ exchange . toUpperCase ( ) } :${ s . symbol } ` ;
147163
148164 return {
149165 id,
150166 exchange,
151167 fullExchange : s . exchange ,
152- screener,
153168 symbol : s . symbol ,
154169 description : s . description ,
155170 type : s . type ,
156- getTA : ( ) => this . getTA ( screener , id ) ,
171+ getTA : ( ) => this . getTA ( id ) ,
157172 } ;
158173 } ) ;
159174 } ,
@@ -182,16 +197,26 @@ module.exports = {
182197 if ( ! builtInIndicList . length ) {
183198 await Promise . all ( [ 'standard' , 'candlestick' , 'fundamental' ] . map ( async ( type ) => {
184199 const { data } = await axios . get (
185- `https://pine-facade.tradingview.com/pine-facade/list/?filter=${ type } ` ,
186- { validateStatus } ,
200+ 'https://pine-facade.tradingview.com/pine-facade/list' ,
201+ {
202+ params : {
203+ filter : type ,
204+ } ,
205+ validateStatus,
206+ } ,
187207 ) ;
188208 builtInIndicList . push ( ...data ) ;
189209 } ) ) ;
190210 }
191211
192212 const { data } = await axios . get (
193- `https://www.tradingview.com/pubscripts-suggest-json/?search=${ search . replace ( / / g, '%20' ) } ` ,
194- { validateStatus } ,
213+ 'https://www.tradingview.com/pubscripts-suggest-json' ,
214+ {
215+ params : {
216+ search : search . replace ( / / g, '%20' ) ,
217+ } ,
218+ validateStatus,
219+ } ,
195220 ) ;
196221
197222 function norm ( str = '' ) {
@@ -253,10 +278,10 @@ module.exports = {
253278 const { data } = await axios . get (
254279 `https://pine-facade.tradingview.com/pine-facade/translate/${ indicID } /${ version } ` ,
255280 {
256- validateStatus,
257281 headers : {
258282 cookie : `${ session ? `sessionid=${ session } ;` : '' } ${ signature ? `sessionid_sign=${ signature } ;` : '' } ` ,
259283 } ,
284+ validateStatus,
260285 } ,
261286 ) ;
262287
@@ -356,12 +381,12 @@ module.exports = {
356381 'https://www.tradingview.com/accounts/signin/' ,
357382 `username=${ username } &password=${ password } ${ remember ? '&remember=on' : '' } ` ,
358383 {
359- validateStatus,
360384 headers : {
361385 referer : 'https://www.tradingview.com' ,
362386 'Content-Type' : 'application/x-www-form-urlencoded' ,
363387 'User-agent' : `${ UA } (${ os . version ( ) } ; ${ os . platform ( ) } ; ${ os . arch ( ) } )` ,
364388 } ,
389+ validateStatus,
365390 } ,
366391 ) ;
367392
@@ -403,10 +428,10 @@ module.exports = {
403428 */
404429 async getUser ( session , signature = '' , location = 'https://www.tradingview.com/' ) {
405430 const { data } = await axios . get ( location , {
406- validateStatus,
407431 headers : {
408432 cookie : `sessionid=${ session } ${ signature ? `;sessionid_sign=${ signature } ;` : '' } ` ,
409433 } ,
434+ validateStatus,
410435 } ) ;
411436
412437 if ( data . includes ( 'auth_token' ) ) {
@@ -442,12 +467,18 @@ module.exports = {
442467 * @returns {Promise<SearchIndicatorResult[]> } Search results
443468 */
444469 async getPrivateIndicators ( session , signature = '' ) {
445- const { data } = await axios . get ( 'https://pine-facade.tradingview.com/pine-facade/list?filter=saved' , {
446- validateStatus,
447- headers : {
448- cookie : `sessionid=${ session } ${ signature ? `;sessionid_sign=${ signature } ;` : '' } ` ,
470+ const { data } = await axios . get (
471+ 'https://pine-facade.tradingview.com/pine-facade/list' ,
472+ {
473+ headers : {
474+ cookie : `sessionid=${ session } ${ signature ? `;sessionid_sign=${ signature } ;` : '' } ` ,
475+ } ,
476+ params : {
477+ filter : 'saved' ,
478+ } ,
479+ validateStatus,
449480 } ,
450- } ) ;
481+ ) ;
451482
452483 return data . map ( ( ind ) => ( {
453484 id : ind . scriptIdPart ,
@@ -495,14 +526,18 @@ module.exports = {
495526 ) ;
496527
497528 const { data } = await axios . get (
498- ` https://www.tradingview.com/chart-token/?image_url= ${ layout } &user_id= ${ id } ` ,
529+ ' https://www.tradingview.com/chart-token' ,
499530 {
500- validateStatus,
501531 headers : {
502532 cookie : session
503533 ? `sessionid=${ session } ${ signature ? `;sessionid_sign=${ signature } ;` : '' } `
504534 : '' ,
505535 } ,
536+ params : {
537+ image_url : layout ,
538+ user_id : id ,
539+ } ,
540+ validateStatus,
506541 } ,
507542 ) ;
508543
@@ -548,14 +583,15 @@ module.exports = {
548583 const { data } = await axios . get (
549584 `https://charts-storage.tradingview.com/charts-storage/get/layout/${
550585 layout
551- } /sources?chart_id=${
552- chartID
553- } &jwt=${
554- chartToken
555- } ${
556- ( symbol ? `&symbol=${ symbol } ` : '' )
557- } `,
558- { validateStatus } ,
586+ } /sources`,
587+ {
588+ params : {
589+ chart_id : chartID ,
590+ jwt : chartToken ,
591+ symbol,
592+ } ,
593+ validateStatus,
594+ } ,
559595 ) ;
560596
561597 if ( ! data . payload ) throw new Error ( 'Wrong layout, user credentials, or chart id.' ) ;
0 commit comments