Open vitorleo opened 2 years ago
I'm happy to contribute via pull request, but I'd need some direction on how you get information about Tradingview's backend / API.
I'm happy to contribute via pull request, but I'd need some direction on how you get information about Tradingview's backend / API.
I'm almost positive he reverse engineers it himself by opening his web browser and going to developer console tools/inpsector and going to Networking -> WebSocket and watching the frames written + read, then inferring himself what the request + responses mean/look like.
curl 'https://pine-facade.tradingview.com/pine-facade/gen_alert/?user_name=brandonros1' \
-H 'authority: pine-facade.tradingview.com' \
-H 'accept: application/json, text/javascript, */*; q=0.01' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \
-H 'cookie: redacted' \
-H 'origin: https://www.tradingview.com' \
-H 'pragma: no-cache' \
-H 'referer: https://www.tradingview.com/' \
-H 'sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-site' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
--data-raw $'alert_info=...' \
--compressed
{
"version": 22,
"condition": {
"id": "alert_0",
"fireInfo": {
"frequency": "on_first_fire"
},
"mainSeries": {
"id": "557963908"
},
"alertSeries": {
"id": "891462776",
"plotIndex": 0
}
},
"statesForAlert": {
"557963908": {
"id": "557963908",
"uniqueId": "557963908",
"type": "MainSeries",
"proSymbol": "AMEX:SPY",
"actualSymbol": "BATS:SPY",
"symbolString": "={\"adjustment\":\"splits\",\"currency-id\":\"USD\",\"session\":\"extended\",\"symbol\":\"BATS:SPY\"}",
"interval": "1",
"style": 1,
"styleInputs": {},
"sessionId": "extended",
"sessionDescription": "Extended trading hours",
"dividendsAdjustment": false,
"backAdjustment": false,
"settlementAsClose": false,
"isSpread": false,
"formatter": {
"type": "price",
"state": {
"fractional": false,
"fractionalLength": 2,
"minMove": 1,
"minMove2": 0,
"priceScale": 100
}
}
},
"891462776": {
"id": "891462776",
"uniqueId": "891462776",
"type": "Study",
"title": "VWAP/MVWAP/EMA CROSSOVER (1, close, 7, close, 25, 65, 51, 21)",
"shortTitle": "VWAP/MVWAP/EMA CROSSOVER (1, close, 7, close, 25, 65, 51, 21)",
"shortDescription": "VWAP/MVWAP/EMA CROSSOVER",
"fullId": "Script$PUB;N16MOYK6AEJGGAoy40axs0S48GRFYcNn@tv-scripting-101",
"isTVScript": true,
"isTVScriptStrategy": false,
"isTVLibrary": false,
"hasAlertFunction": false,
"plots": [
{
"id": "plot_0",
"type": "line",
"pinePlotIndex": 0,
"offset": 0,
"title": "MVWAP",
"text": ""
},
{
"id": "plot_1",
"type": "line",
"pinePlotIndex": 1,
"offset": 0,
"title": "VWAP",
"text": ""
},
{
"id": "plot_2",
"type": "shapes",
"pinePlotIndex": 2,
"offset": 0,
"title": "Long Entry",
"text": "Long"
},
{
"id": "plot_3",
"type": "shapes",
"pinePlotIndex": 3,
"offset": 0,
"title": "Short Entry",
"text": "Short"
},
{
"id": "plot_4",
"type": "shapes",
"pinePlotIndex": 4,
"offset": 0,
"title": "Buy Alert",
"text": ""
},
{
"id": "plot_5",
"type": "shapes",
"pinePlotIndex": 5,
"offset": 0,
"title": "Risky",
"text": ""
},
{
"id": "plot_6",
"type": "shapes",
"pinePlotIndex": 6,
"offset": 0,
"title": "WAIT",
"text": ""
},
{
"id": "plot_7",
"type": "shapes",
"pinePlotIndex": 7,
"offset": 0,
"title": "Enter Here",
"text": ""
},
{
"id": "plot_8",
"type": "line",
"pinePlotIndex": 8,
"offset": 0,
"title": "EMA1",
"text": ""
},
{
"id": "plot_9",
"type": "line",
"pinePlotIndex": 9,
"offset": 0,
"title": "EMA2",
"text": ""
},
{
"id": "plot_11",
"type": "line",
"pinePlotIndex": 11,
"offset": 26,
"title": "Senkou A",
"text": ""
},
{
"id": "plot_12",
"type": "line",
"pinePlotIndex": 12,
"offset": 26,
"title": "Senkou B",
"text": ""
}
],
"inputs": {
"text": "C//1VlAmPXASX5bOdHY3PQ==_DPtdjzfUJ3RzPBVPvQp0AIacOwwkKtFzcq+s/fX46wR5o7LnsS637NBoElUxpSLIz4n6Ri/TOLogDuXKiPhlN1IFzsQHSsgQVGZC+7oqVds//I/IoZRsNxU8WUE+zsKwzxlBzCwPkQfIhjerpgoQx19nV9WSYrihQiGQl1I0CNlG6b7KTB+GWWoSKAqe1qQD12iPAimxfhFhs1iFwOAJizt2SXkh0dSF52FfK4f36s+dLwB8vy1k6PM/FzZ+6zhVfsJiMd2IbBNUDeOI8ybPdqQMJoPNadjEd7TvflSirTTVB3VAHBQcvRBjWYRNJFHMNRbaEST/RZ8BSg5GvD7WhwtWcjn4gxmFZPRcWP8TJ+Z9ivJkNwNWTnFl3naNWZu9TrdN+rrSEtlOimnPRcb87Dhuz7t4NJ/Ni2OJME26nQSwtqKDyfr9mC1UDyuP4YKAbpUXmFtHd1KVmqH605B13MWViW9L5g20Ss1kN30J5+vYu4+8QX5MbjijUt0p3BwiM+Ws10zwQV8qjVZZ8JORJsHpp7jigKGBg/xn4YRzjPpI2iJALdmXmwqOmHY1gpFEYm5T4NWQ4ZVXj+Z41B9PG54Oh9CFMLvohjpOltBaCYQ1y2K9UMstI5S1XYVmSIM9vfxuV1xyU30YDuLX6vTCxS82LyLpGEFljl4/kOGTNPObU7Q5SHBzhQmL4l7MyxjUqjxLiKp6ZRvsL7hPfo3moHVeIC2JI9l9MaA77G/VPTYcjD73UT0pBZ/8qYNDJTvjNf/6uTF15Qdh3JwEiajC88GpPvw5or8J+CfJtQ9x9jG7JUJsyrnXFe1ICwme2avDXtT0hqCEHT9tQDpNqkfRaMK1eZaoz9c2GzQ1vrOWmVVZhUY5F/zr2gLtCt7KYeWRYgsrbJxl68bfYYcoDuuxXnByUB/HpxISQql4dplGhSRkyBS2cYGHfjcHRi3ndkJu5Asy9xxVlCx588AVGC+2ZdckS7y/koYEfDevcAmJ70DALP8+yglQ6Qst7h33KStbYABbADHMML5lTwUesymTyPlkE2zgtBjQNVEGNy+qXbShmke6h4mOg8KK3AYXAuV1Qq76DldjlF/MNkt2XWhO1GYssfZ40qHsehBZLExaHAD8nvzzKdQ/dVYr0exDkkgqt1VZFsdI6JhnglEE3ScO4xvQ8mRodOn/6qoshMQfdSriIggPQkCs48qHVxFE0Jk=",
"pineId": "PUB;N16MOYK6AEJGGAoy40axs0S48GRFYcNn",
"pineVersion": "1.0",
"in_0": {
"v": 1,
"f": true,
"t": "integer"
},
"in_1": {
"v": "close",
"f": true,
"t": "source"
},
"in_2": {
"v": 7,
"f": true,
"t": "integer"
},
"in_3": {
"v": "close",
"f": true,
"t": "source"
},
"in_4": {
"v": 25,
"f": true,
"t": "integer"
},
"in_5": {
"v": 65,
"f": true,
"t": "integer"
},
"in_6": {
"v": 51,
"f": true,
"t": "integer"
},
"in_7": {
"v": 21,
"f": true,
"t": "integer"
}
},
"alerts": {
"conditions": {
"alert_0": {
"message": "Long Alert",
"pineVar": "var_19",
"title": "Long Alert",
"type": "pine_script"
},
"alert_1": {
"message": "Short Alert",
"pineVar": "var_20",
"title": "Short Alert",
"type": "pine_script"
}
}
},
"scriptIdPart": "PUB;N16MOYK6AEJGGAoy40axs0S48GRFYcNn",
"scriptVersion": "1.0",
"callStudyDependencies": "[]",
"studyDependencies": [
{
"id": "891462776",
"study": "Script@tv-scripting-101!",
"inputs": {
"text": "C//1VlAmPXASX5bOdHY3PQ==_DPtdjzfUJ3RzPBVPvQp0AIacOwwkKtFzcq+s/fX46wR5o7LnsS637NBoElUxpSLIz4n6Ri/TOLogDuXKiPhlN1IFzsQHSsgQVGZC+7oqVds//I/IoZRsNxU8WUE+zsKwzxlBzCwPkQfIhjerpgoQx19nV9WSYrihQiGQl1I0CNlG6b7KTB+GWWoSKAqe1qQD12iPAimxfhFhs1iFwOAJizt2SXkh0dSF52FfK4f36s+dLwB8vy1k6PM/FzZ+6zhVfsJiMd2IbBNUDeOI8ybPdqQMJoPNadjEd7TvflSirTTVB3VAHBQcvRBjWYRNJFHMNRbaEST/RZ8BSg5GvD7WhwtWcjn4gxmFZPRcWP8TJ+Z9ivJkNwNWTnFl3naNWZu9TrdN+rrSEtlOimnPRcb87Dhuz7t4NJ/Ni2OJME26nQSwtqKDyfr9mC1UDyuP4YKAbpUXmFtHd1KVmqH605B13MWViW9L5g20Ss1kN30J5+vYu4+8QX5MbjijUt0p3BwiM+Ws10zwQV8qjVZZ8JORJsHpp7jigKGBg/xn4YRzjPpI2iJALdmXmwqOmHY1gpFEYm5T4NWQ4ZVXj+Z41B9PG54Oh9CFMLvohjpOltBaCYQ1y2K9UMstI5S1XYVmSIM9vfxuV1xyU30YDuLX6vTCxS82LyLpGEFljl4/kOGTNPObU7Q5SHBzhQmL4l7MyxjUqjxLiKp6ZRvsL7hPfo3moHVeIC2JI9l9MaA77G/VPTYcjD73UT0pBZ/8qYNDJTvjNf/6uTF15Qdh3JwEiajC88GpPvw5or8J+CfJtQ9x9jG7JUJsyrnXFe1ICwme2avDXtT0hqCEHT9tQDpNqkfRaMK1eZaoz9c2GzQ1vrOWmVVZhUY5F/zr2gLtCt7KYeWRYgsrbJxl68bfYYcoDuuxXnByUB/HpxISQql4dplGhSRkyBS2cYGHfjcHRi3ndkJu5Asy9xxVlCx588AVGC+2ZdckS7y/koYEfDevcAmJ70DALP8+yglQ6Qst7h33KStbYABbADHMML5lTwUesymTyPlkE2zgtBjQNVEGNy+qXbShmke6h4mOg8KK3AYXAuV1Qq76DldjlF/MNkt2XWhO1GYssfZ40qHsehBZLExaHAD8nvzzKdQ/dVYr0exDkkgqt1VZFsdI6JhnglEE3ScO4xvQ8mRodOn/6qoshMQfdSriIggPQkCs48qHVxFE0Jk=",
"pineId": "PUB;N16MOYK6AEJGGAoy40axs0S48GRFYcNn",
"pineVersion": "1.0",
"in_0": {
"v": 1,
"f": true,
"t": "integer"
},
"in_1": {
"v": "close",
"f": true,
"t": "source"
},
"in_2": {
"v": 7,
"f": true,
"t": "integer"
},
"in_3": {
"v": "close",
"f": true,
"t": "source"
},
"in_4": {
"v": 25,
"f": true,
"t": "integer"
},
"in_5": {
"v": 65,
"f": true,
"t": "integer"
},
"in_6": {
"v": 51,
"f": true,
"t": "integer"
},
"in_7": {
"v": 21,
"f": true,
"t": "integer"
}
}
}
],
"formatter": {
"type": "price",
"state": {
"fractional": false,
"fractionalLength": 2,
"minMove": 1,
"minMove2": 0,
"priceScale": 100
}
},
"plotIndex": 0,
"plotOffset": 0
}
},
"message": "1 Long Alert"
}
curl 'https://alerts.tradingview.com/alerts/?log_username=brandonros1&log_method=list_alerts' \
-H 'authority: alerts.tradingview.com' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'cache-control: no-cache' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'cookie: redacted' \
-H 'origin: https://www.tradingview.com' \
-H 'pragma: no-cache' \
-H 'referer: https://www.tradingview.com/' \
-H 'sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-site' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
--data-raw '{"m":"list_alerts","p":{"limit":2000}}' \
--compressed
curl 'https://alerts.tradingview.com/alerts/?log_username=brandonros1&log_method=delete_alerts' \
-H 'authority: alerts.tradingview.com' \
-H 'accept: */*' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'cache-control: no-cache' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'cookie: redacted' \
-H 'origin: https://www.tradingview.com' \
-H 'pragma: no-cache' \
-H 'referer: https://www.tradingview.com/' \
-H 'sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'sec-fetch-dest: empty' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-site: same-site' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
--data-raw '{"m":"delete_alerts","p":{"ids":[603908283]}}' \
--compressed
Does not look like the easiest thing to replicate/reverse.
@brandonros, thanks, this looks good. Can you make a PR ?
@vdun it would not fit inside this repo as you can see without much work.
@Mathieu2301 not sure if you have bandwidth to convert these curl calls into typescript classes the way you'd like
It would be good to have a way to manage alerts programatically.
Describe the solution you'd like Ideally a way to create a new alert from a custom indicator. And then be able to edit the alert and remove it.
Describe alternatives you've considered I've considered simulate the post request from TradingView browser version, but there are some "compiled" text in the payload JSON.
Additional context The idea it to automate the creation of alerts based on user input (just the symbol and timeframe really) from an app that I am developing.