File size: 6,080 Bytes
cb6590e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import aiohttp
import asyncio
import json
import datetime
from enum import Enum
from math import sqrt
import logging

class MarketStatus(Enum):
    # OPEN includes pre-market and post-market
    TRADING = 1
    CLOSED = 2


def format_ws_request(data):
    return f"~m~{len(data)}~m~{data}"


async def get_stock_info(ticker):
    endpoint = f"wss://data.tradingview.com/socket.io/websocket"
    session = aiohttp.ClientSession()
    random_session_id = "qs_PqKEQDeY5hPs"
    async with session.ws_connect(endpoint, origin='https://www.tradingview.com') as ws:
        await ws.receive()
        logging.debug(f"connected to {endpoint}")
        await ws.send_str(format_ws_request('{"m":"set_data_quality","p":["low"]}'))
        await ws.send_str(format_ws_request('{"m":"set_auth_token","p":["unauthorized_user_token"]}'))
        await ws.send_str(format_ws_request('{"m":"set_locale","p":["en","US"]}'))
        await ws.send_str(format_ws_request(f'{{"m":"quote_create_session","p":["{random_session_id}"]}}'))
        # await ws.send_str(format_ws_request(f'{{"m":"quote_set_fields","p":["{random_session_id}","base-currency-logoid","ch","chp","currency-logoid","currency_code","currency_id","base_currency_id","current_session","description","exchange","format","fractional","is_tradable","language","local_description","listed_exchange","logoid","lp","lp_time","minmov","minmove2","original_name","pricescale","pro_name","short_name","type","typespecs","update_mode","volume","variable_tick_size","value_unit_id","ask","bid","fundamentals","high_price","is_tradable","low_price","open_price","prev_close_price","rch","rchp","rtc","rtc_time","status","basic_eps_net_income","beta_1_year","earnings_per_share_basic_ttm","industry","market_cap_basic","price_earnings_ttm","sector","volume","dividends_yield","timezone"]}}'))
        await ws.send_str(format_ws_request(f'{{"m":"quote_add_symbols","p":["{random_session_id}","{ticker}"]}}'))
        await ws.send_str(format_ws_request(f'{{"m":"quote_fast_symbols","p":["{random_session_id}","{ticker}"]}}'))
        logging.debug("sent messages")
        ws_stock_info = await ws.receive()
        logging.debug(ws_stock_info.data)
        await ws.close()
        logging.debug("closed websocket")
        index = 4
        new_stock_info = None
        while new_stock_info is None:
            try:
                stock_info = json.loads(ws_stock_info.data.split("~")[index])["p"][1]
                new_stock_info = {
                    "short_name": stock_info["v"]["short_name"],
                    "name": stock_info["n"],
                    "last_price": stock_info["v"]["lp"],
                    "current_session": MarketStatus.TRADING if stock_info["v"]["current_session"] in ["market", "pre_market", "post_market"] else MarketStatus.CLOSED,
                }
            except KeyError:
                index += 4
        new_stock_info["close_price"] = new_stock_info["last_price"] if new_stock_info["current_session"] == MarketStatus.CLOSED else stock_info["v"]["prev_close_price"]
        new_stock_info["change"] = 0 if new_stock_info["current_session"] == MarketStatus.CLOSED else new_stock_info["last_price"] - new_stock_info["close_price"]
        new_stock_info["change_percent"] = 0 if new_stock_info["current_session"] == MarketStatus.CLOSED else (new_stock_info["last_price"] - new_stock_info["close_price"])/new_stock_info["last_price"] * 100
        return new_stock_info


async def get_technical_rating(ticker, time=None, adjust=None):
    headers = {
        'authority': 'scanner.tradingview.com',
        'accept': 'application/json',
        'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8,zh-Hans;q=0.7,zh;q=0.6',
        'cache-control': 'no-cache',
        # 'cookie': 'cookiePrivacyPreferenceBannerProduction=notApplicable; cookiesSettings={"analytics":true,"advertising":true}; device_t=TGdRUEJBOjA.DsY7yfR2BGUIu_pO-s2MDpMczSLpYWQXBZVedEgbwks; sessionid=m4vktjbp6w9tw0noiyy56cu5djsz3b3k; sessionid_sign=v1:7+2774aIu7zFlHqM7hPs01NHuPzTxJGiz40C0U4ofts=; tv_ecuid=61f7b49d-5ff0-460e-a9c6-f4f08384b31e; cachec=61f7b49d-5ff0-460e-a9c6-f4f08384b31e; etg=61f7b49d-5ff0-460e-a9c6-f4f08384b31e; _ga=GA1.1.1541556038.1701929137; _ga_YVVRYGL0E0=GS1.1.1702701849.26.1.1702702103.60.0.0; _sp_id.cf1a=2f870214-eb23-490e-821b-b3632a37c876.1701906159.44.1704694255.1704532038.1ccd4fce-568b-4d9f-8495-4e675b3cb00e',
        'origin': 'https://www.tradingview.com',
        'pragma': 'no-cache',
        'referer': 'https://www.tradingview.com/',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"macOS"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    }
    params = {
        "symbol": ticker,
        "no_404": "true",
    }
    if time is not None:
        params["fields"] = "Recommend.All" + time
    else:
        params["fields"] = "Recommend.All"
    tries = 0
    async with aiohttp.ClientSession() as session:
        logging.debug(f"Getting URL https://scanner.tradingview.com/symbol...")
        while tries < 5:
            try:
                rating = await session.get("https://scanner.tradingview.com/symbol", params=params, headers=headers, timeout=20)
                rating = await rating.json()
                logging.debug(rating)
                rating = list(rating.values())[0]
                adjust = False if adjust is None else adjust

                if adjust:
                    if rating < 0:
                        return sqrt(rating * -1) * -1
                    else:
                        return sqrt(rating)
                else:
                    return rating
            except:
                tries += 1
                if tries >= 5:
                    raise asyncio.exceptions.TimeoutError(f"Failed to fetch info after {tries} tries")