5

I am able to get live ticker data and the prior 500-100 candle chart data with this code but I am unable to get data that isn't delayed for CME_MINI:ESH2021. TradingView puts a 600 second delay I believe on the public stream. I do pay for the data and I can pull it up on the web client but I am unable to get the non-delayed data on python since I am unsure how to log into TradingView via python. If someone knows how I can fix my code to do what I want it to I would greatly appreciate your input or any advice.

from websocket import create_connection
import json
import random
import string
import re
from datetime import datetime
from time import sleep

def filter_raw_message(text):
try:
    found = re.search('"p":(.+?"}"])}', text).group(1)
    print(found)
    return found
except AttributeError:
    print("error")


def generateSession():
stringLength=12
letters = string.ascii_lowercase
random_string= ''.join(random.choice(letters) for i in range(stringLength))
return "qs_" +random_string

def generateChartSession():
stringLength=12
letters = string.ascii_lowercase
random_string= ''.join(random.choice(letters) for i in range(stringLength))
return "cs_" +random_string

def prependHeader(st):
return "~m~" + str(len(st)) + "~m~" + st

def constructMessage(func, paramList):
#json_mylist = json.dumps(mylist, separators=(',', ':'))
return json.dumps({
    "m":func,
    "p":paramList
    }, separators=(',', ':'))

def createMessage(func, paramList):
return prependHeader(constructMessage(func, paramList))

def sendRawMessage(ws, message):
ws.send(prependHeader(message))

def sendMessage(ws, func, args):
ws.send(createMessage(func, args))
    
# Initialize the headers needed for the websocket connection
headers = json.dumps({
'Connection': 'upgrade',
'Host': 'data.tradingview.com',
'Origin': 'https://data.tradingview.com',
'Cache-Control': 'no-cache',
'Upgrade': 'websocket',
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
'Sec-WebSocket-Key': '1H41q97V8BbMKUq0knV1UA==',
'Sec-WebSocket-Version': '13',
'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.56',
'Pragma': 'no-cache',
'Upgrade': 'websocket'
})

# Then create a connection to the tunnel
ws = create_connection(
'wss://data.tradingview.com/socket.io/websocket',headers=headers)

session= generateSession()
print("session generated {}".format(session))

chart_session= generateChartSession()
print("chart_session generated {}".format(chart_session))

symbol = "CME_MINI:ESH2021"
timeframe = "5"
candles = 100

# Then send a message through the tunnel 
sendMessage(ws, "set_auth_token", ["unauthorized_user_token"])
sendMessage(ws, "chart_create_session", [chart_session, ""])
sendMessage(ws, "quote_create_session", [session])
sendMessage(ws,"quote_set_fields", [session,"ch","chp","current_session","description","local_description","language","exchange","fractional","is_tradable","lp","lp_time","minmov","minmove2","original_name","pricescale","pro_name","short_name","type","update_mode","volume","currency_code","rchp","rtc"])
sendMessage(ws, "quote_add_symbols",[session, symbol, {"flags":['force_permission']}])

theString1 = "={\"symbol\":\""
theString2 = "\",\"adjustment\":\"splits\"}"
theString3 = theString1 + symbol + theString2

sendMessage(ws, "resolve_symbol", [chart_session, "symbol_" + timeframe, theString3])
sendMessage(ws, "create_series", [chart_session,"s" + timeframe,"s" + timeframe,"symbol_" + timeframe,timeframe,candles])

sendMessage(ws, "quote_fast_symbols", [session,symbol])

sendMessage(ws, "create_study", [chart_session,"st" + timeframe,"st" + timeframe,"s" + timeframe,"Volume@tv-basicstudies-118",{"length":20,"col_prev_close":"false"}])
sendMessage(ws, "quote_hibernate_all", [session])

# Printing all the result
a=""
while True:
try:
    sleep(1)
    result = ws.recv()
    pattern = re.compile("~m~\d+~m~~h~\d+$")
    if pattern.match(result):
        ws.recv()
        ws.send(result)
        print("\n\n\n hhhhhhhhhhhhhhhhhhhhhh "+ str(result) + "\n\n")
    print(result)
    a=a+result+"\n"
except Exception as e:
    print(e)
    break
PaulRydberg
  • 51
  • 1
  • 3

2 Answers2

3

This post is quite old, and the OP probably has the answer already, but regardless, I'm posting for people who visit this page in the future.

This solution comes from the Github page here: https://github.com/rushic24/tradingview-scraper

In fact, what I'm about to post is literally on the front page of that link. I'm just remaking it into a step-by-step guide.

In the original code, you can find the following line:

sendMessage(ws, "set_auth_token", ["unauthorized_user_token"])

Do you see the part where it says "unauthorized_user_token"? That means you're an anonymous random person to TradingView. So you must create an auth_token to let TradingView know you're logging in as yourself and that you indeed have paid access to real-time data.

1.

Add the following to your code:

def get_auth_token():
    sign_in_url = 'https://www.tradingview.com/accounts/signin/'
    username = 'username'
    password = 'password'
    data = {"username": username, "password": password, "remember": "on"}
    headers = {
        'Referer': 'https://www.tradingview.com'
    }
    response = requests.post(url=sign_in_url, data=data, headers=headers)
    auth_token = response.json()['user']['auth_token']    
    return auth_token

Replace 'username' and 'password' with your own.

2.

replace

sendMessage(ws, "set_auth_token", ["unauthorized_user_token"])

With the following:

auth_token = get_auth_token()
sendMessage(ws, "set_auth_token", [auth_token])

replace

ws = create_connection('wss://data.tradingview.com/socket.io/websocket', headers=headers)

With the following:

ws = create_connection( 'wss://data.tradingview.com/socket.io/websocket?from=chart/XXyour_chartXX/&date=XXXX_XX_XX-XX_XX',headers=headers)

replace 'XXyour_chartXX' with one of your saved charts' URLs. (https://www.tradingview.com/chart/***###THIS_PART###***/)

RuBYGlyPh
  • 31
  • 3
  • Thanks. `set_auth_token` is a function name, right? I don't see it defined anywhere in the code. – fire_water Jul 31 '22 at 19:44
  • 1
    @fire_water sorry for the late reply. It's not a function. And I'm not 100% sure on this but I think "set_auth_token" is something that Tradingview wants to see when they receive the authentication token via sendMessage() method, so I think it's better to not change it. – RuBYGlyPh Aug 05 '22 at 08:40
  • @RuBYGlyPh, any luck pulling data from a study/indicator? seems to require a hashed "text" field that rotates every session.. – alps Mar 18 '23 at 15:41
0

this is very useful, thanks a ton! I guess it only works with the 2FA disabled, otherwise it throws this "{'error': '2FA_required', 'code': '2FA_required', 'message': 'Second authentication factor is needed', 'two_factor_types': [{'name': 'totp'}]}"

Silviu
  • 135
  • 1
  • 9