From cddf9898b2f32e96d66fd52972f31f82cf3d1c7d Mon Sep 17 00:00:00 2001 From: AbdAlftahSalem Date: Sat, 24 Jun 2023 21:12:02 +0300 Subject: [PATCH 1/5] Add indecator --- .idea/.gitignore | 3 + .idea/inspectionProfiles/Project_Default.xml | 82 ++++++++ .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/python-tradingview-ta.iml | 14 ++ .idea/vcs.xml | 6 + tradingview_ta/main.py | 178 ++++++++++++++++-- 8 files changed, 288 insertions(+), 13 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/python-tradingview-ta.iml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..2bdc722 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,82 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..af36f7e --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f26a588 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/python-tradingview-ta.iml b/.idea/python-tradingview-ta.iml new file mode 100644 index 0000000..269e1a8 --- /dev/null +++ b/.idea/python-tradingview-ta.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tradingview_ta/main.py b/tradingview_ta/main.py index 0c8638b..2a4cd87 100644 --- a/tradingview_ta/main.py +++ b/tradingview_ta/main.py @@ -2,11 +2,13 @@ # Author: deathlyface (https://github.com/deathlyface) # License: MIT -import requests -import json import datetime +import json import warnings -from .technicals import Compute + +import requests + +from technicals import Compute __version__ = "3.3.0" @@ -43,8 +45,21 @@ class Exchange: class TradingView: # Note: Please DO NOT modify the order or DELETE existing indicators, it will break the technical analysis. You may APPEND custom indicator to the END of the list. - indicators = ["Recommend.Other", "Recommend.All", "Recommend.MA", "RSI", "RSI[1]", "Stoch.K", "Stoch.D", "Stoch.K[1]", "Stoch.D[1]", "CCI20", "CCI20[1]", "ADX", "ADX+DI", "ADX-DI", "ADX+DI[1]", "ADX-DI[1]", "AO", "AO[1]", "Mom", "Mom[1]", "MACD.macd", "MACD.signal", "Rec.Stoch.RSI", "Stoch.RSI.K", "Rec.WR", "W.R", "Rec.BBPower", "BBPower", "Rec.UO", "UO", "close", "EMA5", "SMA5", "EMA10", "SMA10", "EMA20", "SMA20", "EMA30", "SMA30", "EMA50", "SMA50", "EMA100", "SMA100", "EMA200", "SMA200", "Rec.Ichimoku", "Ichimoku.BLine", "Rec.VWMA", "VWMA", "Rec.HullMA9", "HullMA9", "Pivot.M.Classic.S3", "Pivot.M.Classic.S2", "Pivot.M.Classic.S1", "Pivot.M.Classic.Middle", "Pivot.M.Classic.R1", - "Pivot.M.Classic.R2", "Pivot.M.Classic.R3", "Pivot.M.Fibonacci.S3", "Pivot.M.Fibonacci.S2", "Pivot.M.Fibonacci.S1", "Pivot.M.Fibonacci.Middle", "Pivot.M.Fibonacci.R1", "Pivot.M.Fibonacci.R2", "Pivot.M.Fibonacci.R3", "Pivot.M.Camarilla.S3", "Pivot.M.Camarilla.S2", "Pivot.M.Camarilla.S1", "Pivot.M.Camarilla.Middle", "Pivot.M.Camarilla.R1", "Pivot.M.Camarilla.R2", "Pivot.M.Camarilla.R3", "Pivot.M.Woodie.S3", "Pivot.M.Woodie.S2", "Pivot.M.Woodie.S1", "Pivot.M.Woodie.Middle", "Pivot.M.Woodie.R1", "Pivot.M.Woodie.R2", "Pivot.M.Woodie.R3", "Pivot.M.Demark.S1", "Pivot.M.Demark.Middle", "Pivot.M.Demark.R1", "open", "P.SAR", "BB.lower", "BB.upper", "AO[2]", "volume", "change", "low", "high"] + indicators = ["Recommend.Other", "Recommend.All", "Recommend.MA", "RSI", "RSI[1]", "Stoch.K", "Stoch.D", + "Stoch.K[1]", "Stoch.D[1]", "CCI20", "CCI20[1]", "ADX", "ADX+DI", "ADX-DI", "ADX+DI[1]", "ADX-DI[1]", + "AO", "AO[1]", "Mom", "Mom[1]", "MACD.macd", "MACD.signal", "Rec.Stoch.RSI", "Stoch.RSI.K", "Rec.WR", + "W.R", "Rec.BBPower", "BBPower", "Rec.UO", "UO", "close", "EMA5", "SMA5", "EMA10", "SMA10", "EMA20", + "SMA20", "EMA30", "SMA30", "EMA50", "SMA50", "EMA100", "SMA100", "EMA200", "SMA200", "Rec.Ichimoku", + "Ichimoku.BLine", "Rec.VWMA", "VWMA", "Rec.HullMA9", "HullMA9", "Pivot.M.Classic.S3", + "Pivot.M.Classic.S2", "Pivot.M.Classic.S1", "Pivot.M.Classic.Middle", "Pivot.M.Classic.R1", + "Pivot.M.Classic.R2", "Pivot.M.Classic.R3", "Pivot.M.Fibonacci.S3", "Pivot.M.Fibonacci.S2", + "Pivot.M.Fibonacci.S1", "Pivot.M.Fibonacci.Middle", "Pivot.M.Fibonacci.R1", "Pivot.M.Fibonacci.R2", + "Pivot.M.Fibonacci.R3", "Pivot.M.Camarilla.S3", "Pivot.M.Camarilla.S2", "Pivot.M.Camarilla.S1", + "Pivot.M.Camarilla.Middle", "Pivot.M.Camarilla.R1", "Pivot.M.Camarilla.R2", "Pivot.M.Camarilla.R3", + "Pivot.M.Woodie.S3", "Pivot.M.Woodie.S2", "Pivot.M.Woodie.S1", "Pivot.M.Woodie.Middle", + "Pivot.M.Woodie.R1", "Pivot.M.Woodie.R2", "Pivot.M.Woodie.R3", "Pivot.M.Demark.S1", + "Pivot.M.Demark.Middle", "Pivot.M.Demark.R1", "open", "P.SAR", "BB.lower", "BB.upper", "AO[2]", + "volume", "change", "low", "high"] scan_url = "https://scanner.tradingview.com/" @@ -97,6 +112,75 @@ def data(symbols, interval, indicators): return data_json + def data_multi_intervals(symbols, intervals, indicators): + """Format TradingView's Scanner Post Data + + Args: + symbols (list): List of EXCHANGE:SYMBOL (ex: ["NASDAQ:AAPL"] or ["BINANCE:BTCUSDT"]) + interval (list): Time Interval (ex: 1m, 5m, 15m, 1h, 4h, 1d, 1W, 1M) + + Returns: + string: JSON object as a string. + """ + output_intervals = [] + for interval in intervals: + if interval == "1m": + # 1 Minute + data_interval = "|1" + output_intervals.append(data_interval) + elif interval == "5m": + # 5 Minutes + data_interval = "|5" + output_intervals.append(data_interval) + + elif interval == "15m": + # 15 Minutes + data_interval = "|15" + output_intervals.append(data_interval) + + elif interval == "30m": + # 30 Minutes + data_interval = "|30" + output_intervals.append(data_interval) + + elif interval == "1h": + # 1 Hour + data_interval = "|60" + output_intervals.append(data_interval) + + elif interval == "2h": + # 2 Hours + data_interval = "|120" + output_intervals.append(data_interval) + + elif interval == "4h": + # 4 Hour + data_interval = "|240" + output_intervals.append(data_interval) + + elif interval == "1W": + # 1 Week + data_interval = "|1W" + output_intervals.append(data_interval) + + elif interval == "1M": + # 1 Month + data_interval = "|1M" + output_intervals.append(data_interval) + + else: + if interval != '1d': + warnings.warn( + "Interval is empty or not valid, defaulting to 1 day.") + # Default, 1 Day + data_interval = "" + output_intervals.append(data_interval) + + data_json = {"symbols": {"tickers": [symbol.upper() for symbol in symbols], "query": { + "types": []}}, "columns": [i + j for j in output_intervals for i in indicators]} + + return data_json + def search(text, type=None): """Search for assets on TradingView. Returns the symbol, exchange, type, and description of the asset. @@ -228,11 +312,14 @@ def calculate(indicators, indicators_key, screener, symbol, exchange, interval): analysis.indicators = analysis.indicators.copy() analysis.oscillators = {"RECOMMENDATION": recommend_oscillators, - "BUY": oscillators_counter["BUY"], "SELL": oscillators_counter["SELL"], "NEUTRAL": oscillators_counter["NEUTRAL"], "COMPUTE": computed_oscillators} + "BUY": oscillators_counter["BUY"], "SELL": oscillators_counter["SELL"], + "NEUTRAL": oscillators_counter["NEUTRAL"], "COMPUTE": computed_oscillators} analysis.moving_averages = {"RECOMMENDATION": recommend_moving_averages, - "BUY": ma_counter["BUY"], "SELL": ma_counter["SELL"], "NEUTRAL": ma_counter["NEUTRAL"], "COMPUTE": computed_ma} + "BUY": ma_counter["BUY"], "SELL": ma_counter["SELL"], "NEUTRAL": ma_counter["NEUTRAL"], + "COMPUTE": computed_ma} analysis.summary = {"RECOMMENDATION": recommend_summary, "BUY": oscillators_counter["BUY"] + ma_counter["BUY"], - "SELL": oscillators_counter["SELL"] + ma_counter["SELL"], "NEUTRAL": oscillators_counter["NEUTRAL"] + ma_counter["NEUTRAL"]} + "SELL": oscillators_counter["SELL"] + ma_counter["SELL"], + "NEUTRAL": oscillators_counter["NEUTRAL"] + ma_counter["NEUTRAL"]} return analysis @@ -355,8 +442,9 @@ def get_indicators(self, indicators=[]): # Return False if can't get data if response.status_code != 200: - raise Exception("Can't access TradingView's API. HTTP status code: {}. Check for invalid symbol, exchange, or indicators.".format( - response.status_code)) + raise Exception( + "Can't access TradingView's API. HTTP status code: {}. Check for invalid symbol, exchange, or indicators.".format( + response.status_code)) result = json.loads(response.text)["data"] if result != []: @@ -384,7 +472,8 @@ def get_analysis(self): Analysis: Contains information about the analysis. """ - return calculate(indicators=self.get_indicators(), indicators_key=self.indicators, screener=self.screener, symbol=self.symbol, exchange=self.exchange, interval=self.interval) + return calculate(indicators=self.get_indicators(), indicators_key=self.indicators, screener=self.screener, + symbol=self.symbol, exchange=self.exchange, interval=self.interval) def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], timeout=None, proxies=None): @@ -430,8 +519,9 @@ def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], for x in range(len(analysis["d"])): indicators[indicators_key[x]] = analysis["d"][x] - final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, symbol=analysis["s"].split( - ":")[1], exchange=analysis["s"].split(":")[0], interval=interval) + final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, + symbol=analysis["s"].split( + ":")[1], exchange=analysis["s"].split(":")[0], interval=interval) for symbol in symbols: # Add None if there is no analysis for symbol @@ -439,3 +529,65 @@ def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], final[symbol.upper()] = None return final + + +def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, additional_indicators=[], timeout=None, + proxies=None): + """Retrieve multiple technical analysis at once. Note: You can't mix different screener and interval + + Args: + screener (str, required): Screener (see documentation and tradingview's site). + interval (str, optional): See the interval class and the documentation. Defaults to 1 day. + symbols (list, required): List of exchange and ticker symbol separated by a colon. Example: ["NASDAQ:TSLA", "NYSE:DOCN"] or ["BINANCE:BTCUSDT", "BITSTAMP:ETHUSD"]. + additional_indicators (list, optional): List of additional indicators to be requested from TradingView, see valid indicators on https://pastebin.com/1DjWv2Hd. + timeout (float, optional): Timeout for requests (in seconds). Defaults to None. + proxies (dict, optional): Proxies to be used for requests. Defaults to None (disabled). + + Returns: + dict: dictionary with a format of {"EXCHANGE:SYMBOL": Analysis}. + """ + if screener == "" or type(screener) != str: + raise Exception("Screener is empty or not valid.") + if len(symbols) == 0 or type(symbols) != list: + raise Exception("Symbols is empty or not valid.") + for symbol in symbols: + if len(symbol.split(":")) != 2 or "" in symbol.split(":"): + raise Exception( + "One or more symbol is invalid. Symbol should be a list of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].") + + indicators_key = TradingView.indicators.copy() + + if additional_indicators: + indicators_key += additional_indicators + + data = TradingView.data_multi_intervals(symbols, intervals, indicators_key) + # scan_url = f"{TradingView.scan_url}{screener.lower()}/scan" + # headers = {"User-Agent": "tradingview_ta/{}".format(__version__)} + # response = requests.post( + # scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) + # + # result = json.loads(response.text)["data"] + # final = {} + # + # for analysis in result: + # # Convert list to dict + # indicators = {} + # for x in range(len(analysis["d"])): + # indicators[indicators_key[x]] = analysis["d"][x] + # + # final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, + # symbol=analysis["s"].split( + # ":")[1], exchange=analysis["s"].split(":")[0], interval=intervals) + # + # for symbol in symbols: + # # Add None if there is no analysis for symbol + # if symbol.upper() not in final: + # final[symbol.upper()] = None + + # return final + + +# new_dict = {key: value for key, value in final["BINANCE:BTCUSDT"].indicators.items() if key.endswith('|1')} +# print(new_dict) +# print(interval) +get_multiple_analysis_with_multiple_intervals(screener="crypto", intervals=["1m", "5m"], symbols=["BINANCE:BTCUSDT"]) From 09de3098f131a6a5c103a1869fb801a0cadaf389 Mon Sep 17 00:00:00 2001 From: AbdAlftahSalem Date: Sat, 24 Jun 2023 21:49:19 +0300 Subject: [PATCH 2/5] udpate code with dict --- tradingview_ta/main.py | 113 ++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/tradingview_ta/main.py b/tradingview_ta/main.py index 2a4cd87..86128fc 100644 --- a/tradingview_ta/main.py +++ b/tradingview_ta/main.py @@ -531,6 +531,42 @@ def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], return final +def get_end_with(interval): + if interval == "1m": + # 1 Minute + return "|1" + elif interval == "5m": + # 5 Minutes + return "|5" + elif interval == "15m": + # 15 Minutes + return "|15" + elif interval == "30m": + # 30 Minutes + return "|30" + elif interval == "1h": + # 1 Hour + return "|60" + elif interval == "2h": + # 2 Hours + return "|120" + elif interval == "4h": + # 4 Hour + return "|240" + elif interval == "1W": + # 1 Week + return "|1W" + elif interval == "1M": + # 1 Month + return "|1M" + else: + if interval != '1d': + warnings.warn( + "Interval is empty or not valid, defaulting to 1 day.") + # Default, 1 Day + return "|1D" + + def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, additional_indicators=[], timeout=None, proxies=None): """Retrieve multiple technical analysis at once. Note: You can't mix different screener and interval @@ -561,28 +597,58 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, indicators_key += additional_indicators data = TradingView.data_multi_intervals(symbols, intervals, indicators_key) - # scan_url = f"{TradingView.scan_url}{screener.lower()}/scan" - # headers = {"User-Agent": "tradingview_ta/{}".format(__version__)} - # response = requests.post( - # scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) - # - # result = json.loads(response.text)["data"] - # final = {} - # - # for analysis in result: - # # Convert list to dict - # indicators = {} - # for x in range(len(analysis["d"])): - # indicators[indicators_key[x]] = analysis["d"][x] - # - # final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, - # symbol=analysis["s"].split( - # ":")[1], exchange=analysis["s"].split(":")[0], interval=intervals) - # - # for symbol in symbols: - # # Add None if there is no analysis for symbol - # if symbol.upper() not in final: - # final[symbol.upper()] = None + indicators_key = data["columns"] + scan_url = f"{TradingView.scan_url}{screener.lower()}/scan" + headers = {"User-Agent": "tradingview_ta/{}".format(__version__)} + response = requests.post( + scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) + + result = json.loads(response.text)["data"] + print(result) + final = {} + + for analysis in result: + # Convert list to dict + indicators = {} + for x in range(len(analysis["d"])): + indicators[indicators_key[x]] = analysis["d"][x] + + final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, + symbol=analysis["s"].split( + ":")[1], exchange=analysis["s"].split(":")[0], interval=intervals) + + for symbol in symbols: + # Add None if there is no analysis for symbol + if symbol.upper() not in final: + final[symbol.upper()] = None + + for i in symbols: + dict_1m = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1')} + dict_5m = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|5')} + dict_15m = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|15')} + dict_30m = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|30')} + dict_1h = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|60')} + dict_2h = {key[:-4]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|120')} + dict_4h = {key[:-4]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|240')} + dict_1W = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1W')} + dict_1M = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1M')} + dict_1D = {key: value for key, value in final[i.upper()].indicators.items() if '|' not in key} + + + final[i.upper()].indicators = { + "1m": dict_1m, + "5m": dict_5m, + "15m": dict_15m, + "30m": dict_30m, + "1h": dict_1h, + "2h": dict_2h, + "4h": dict_4h, + "1W": dict_1W, + "1M": dict_1M, + "1d": dict_1D, + } + + print(final[i.upper()].indicators) # return final @@ -590,4 +656,5 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, # new_dict = {key: value for key, value in final["BINANCE:BTCUSDT"].indicators.items() if key.endswith('|1')} # print(new_dict) # print(interval) -get_multiple_analysis_with_multiple_intervals(screener="crypto", intervals=["1m", "5m"], symbols=["BINANCE:BTCUSDT"]) +get_multiple_analysis_with_multiple_intervals(screener="crypto", intervals=["1d"], + symbols=["BINANCE:SOLUSDT"]) From 8a68c1c9c574601c29e17ef4fdd132eacccca82b Mon Sep 17 00:00:00 2001 From: AbdAlftahSalem Date: Sat, 24 Jun 2023 22:02:31 +0300 Subject: [PATCH 3/5] Finish add multiple frames with multiple symbols --- tradingview_ta/main.py | 92 ++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/tradingview_ta/main.py b/tradingview_ta/main.py index 86128fc..e927d2a 100644 --- a/tradingview_ta/main.py +++ b/tradingview_ta/main.py @@ -604,7 +604,6 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) result = json.loads(response.text)["data"] - print(result) final = {} for analysis in result: @@ -622,39 +621,62 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, if symbol.upper() not in final: final[symbol.upper()] = None + combain_dict = {} for i in symbols: - dict_1m = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1')} - dict_5m = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|5')} - dict_15m = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|15')} - dict_30m = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|30')} - dict_1h = {key[:-3]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|60')} - dict_2h = {key[:-4]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|120')} - dict_4h = {key[:-4]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|240')} - dict_1W = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1W')} - dict_1M = {key[:-2]: value for key, value in final[i.upper()].indicators.items() if key.endswith('|1M')} - dict_1D = {key: value for key, value in final[i.upper()].indicators.items() if '|' not in key} - - - final[i.upper()].indicators = { - "1m": dict_1m, - "5m": dict_5m, - "15m": dict_15m, - "30m": dict_30m, - "1h": dict_1h, - "2h": dict_2h, - "4h": dict_4h, - "1W": dict_1W, - "1M": dict_1M, - "1d": dict_1D, - } - - print(final[i.upper()].indicators) - - # return final - - -# new_dict = {key: value for key, value in final["BINANCE:BTCUSDT"].indicators.items() if key.endswith('|1')} -# print(new_dict) -# print(interval) -get_multiple_analysis_with_multiple_intervals(screener="crypto", intervals=["1d"], + if Interval.INTERVAL_1_MINUTE in intervals: + dict_1m = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|1')} + combain_dict[Interval.INTERVAL_1_MINUTE] = dict_1m + + if Interval.INTERVAL_5_MINUTES in intervals: + dict_5m = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|5')} + combain_dict[Interval.INTERVAL_5_MINUTES] = dict_5m + + if Interval.INTERVAL_15_MINUTES in intervals: + dict_15m = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|15')} + combain_dict[Interval.INTERVAL_15_MINUTES] = dict_15m + + if Interval.INTERVAL_30_MINUTES in intervals: + dict_30m = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|30')} + combain_dict[Interval.INTERVAL_30_MINUTES] = dict_30m + + if Interval.INTERVAL_1_HOUR in intervals: + dict_1h = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|60')} + combain_dict[Interval.INTERVAL_1_HOUR] = dict_1h + + if Interval.INTERVAL_2_HOURS in intervals: + dict_2h = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|120')} + combain_dict[Interval.INTERVAL_2_HOURS] = dict_2h + + if Interval.INTERVAL_4_HOURS in intervals: + dict_4h = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|240')} + combain_dict[Interval.INTERVAL_4_HOURS] = dict_4h + + if Interval.INTERVAL_1_WEEK in intervals: + dict_1W = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|1W')} + combain_dict[Interval.INTERVAL_1_WEEK] = dict_1W + + if Interval.INTERVAL_1_MONTH in intervals: + dict_1M = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if + key.endswith('|1M')} + combain_dict[Interval.INTERVAL_1_MONTH] = dict_1M + + if Interval.INTERVAL_1_DAY in intervals: + dict_1D = {key.split("|")[0]: value for key, value in final[i.upper()].indicators.items() if '|' not in key} + combain_dict[Interval.INTERVAL_1_DAY] = dict_1D + + final[i.upper()].indicators = combain_dict + + return final + + +get_multiple_analysis_with_multiple_intervals(screener="crypto", + intervals=[Interval.INTERVAL_1_DAY], symbols=["BINANCE:SOLUSDT"]) From 05be90ce17bc3fe5f54e1a074b828ec3c2b81a3f Mon Sep 17 00:00:00 2001 From: AbdAlftahSalem Date: Sat, 24 Jun 2023 22:22:24 +0300 Subject: [PATCH 4/5] Update --- tradingview_ta/main.py | 56 +++++++----------------------------------- 1 file changed, 9 insertions(+), 47 deletions(-) diff --git a/tradingview_ta/main.py b/tradingview_ta/main.py index e927d2a..bf70e74 100644 --- a/tradingview_ta/main.py +++ b/tradingview_ta/main.py @@ -531,42 +531,6 @@ def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], return final -def get_end_with(interval): - if interval == "1m": - # 1 Minute - return "|1" - elif interval == "5m": - # 5 Minutes - return "|5" - elif interval == "15m": - # 15 Minutes - return "|15" - elif interval == "30m": - # 30 Minutes - return "|30" - elif interval == "1h": - # 1 Hour - return "|60" - elif interval == "2h": - # 2 Hours - return "|120" - elif interval == "4h": - # 4 Hour - return "|240" - elif interval == "1W": - # 1 Week - return "|1W" - elif interval == "1M": - # 1 Month - return "|1M" - else: - if interval != '1d': - warnings.warn( - "Interval is empty or not valid, defaulting to 1 day.") - # Default, 1 Day - return "|1D" - - def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, additional_indicators=[], timeout=None, proxies=None): """Retrieve multiple technical analysis at once. Note: You can't mix different screener and interval @@ -582,14 +546,14 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, Returns: dict: dictionary with a format of {"EXCHANGE:SYMBOL": Analysis}. """ - if screener == "" or type(screener) != str: + if not screener or not isinstance(screener, str): raise Exception("Screener is empty or not valid.") - if len(symbols) == 0 or type(symbols) != list: + if not symbols or not isinstance(symbols, list): raise Exception("Symbols is empty or not valid.") for symbol in symbols: if len(symbol.split(":")) != 2 or "" in symbol.split(":"): raise Exception( - "One or more symbol is invalid. Symbol should be a list of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].") + "One or more symbols are invalid. Symbols should be a list of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].") indicators_key = TradingView.indicators.copy() @@ -600,21 +564,18 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, indicators_key = data["columns"] scan_url = f"{TradingView.scan_url}{screener.lower()}/scan" headers = {"User-Agent": "tradingview_ta/{}".format(__version__)} - response = requests.post( - scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) + response = requests.post(scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies) result = json.loads(response.text)["data"] final = {} for analysis in result: # Convert list to dict - indicators = {} - for x in range(len(analysis["d"])): - indicators[indicators_key[x]] = analysis["d"][x] + indicators = {indicators_key[x]: analysis["d"][x] for x in range(len(analysis["d"]))} final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, - symbol=analysis["s"].split( - ":")[1], exchange=analysis["s"].split(":")[0], interval=intervals) + symbol=analysis["s"].split(":")[1], exchange=analysis["s"].split(":")[0], + interval=intervals) for symbol in symbols: # Add None if there is no analysis for symbol @@ -674,9 +635,10 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, final[i.upper()].indicators = combain_dict + print(final["BINANCE:SOLUSDT"].indicators) return final get_multiple_analysis_with_multiple_intervals(screener="crypto", - intervals=[Interval.INTERVAL_1_DAY], + intervals=[Interval.INTERVAL_1_DAY, Interval.INTERVAL_1_HOUR], symbols=["BINANCE:SOLUSDT"]) From 2059a6bfda5ae195c72af9b9a6a334265d1c5dbf Mon Sep 17 00:00:00 2001 From: AbdAlftahSalem Date: Sat, 24 Jun 2023 22:29:10 +0300 Subject: [PATCH 5/5] Add on test --- test.py | 25 ++++++++++++++++++++++++- tradingview_ta/__init__.py | 3 ++- tradingview_ta/main.py | 8 +------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/test.py b/test.py index b5b513c..851db77 100644 --- a/test.py +++ b/test.py @@ -1,5 +1,5 @@ from colorama import Fore, Style -from tradingview_ta import TA_Handler, Interval, get_multiple_analysis +from tradingview_ta import TA_Handler, Interval, get_multiple_analysis, get_multiple_analysis_with_multiple_intervals import tradingview_ta, requests, argparse arg_parser = argparse.ArgumentParser() @@ -152,6 +152,29 @@ except Exception as e: print("{}#6{} Get indicators test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e)) +try: + analysis = get_multiple_analysis_with_multiple_intervals(screener="crypto", + intervals=[Interval.INTERVAL_1_DAY, + Interval.INTERVAL_1_HOUR], + symbols=["BINANCE:SOLUSDT", "BINANCE:BTCUSDT"]) + for key, value in analysis.items(): + print( + "{}#7{} Please compare with {}https://www.tradingview.com/symbols/{}/technicals/{}. (Switch to 1 hour tab)".format( + Fore.BLUE, Style.RESET_ALL, Fore.LIGHTMAGENTA_EX, key, Style.RESET_ALL)) + print("{}#7{} (Summary) Rec: {}, Sell: {}, Neutral: {}, Buy: {}".format(Fore.BLUE, Style.RESET_ALL, + value.summary["RECOMMENDATION"], + value.summary["SELL"], + value.summary["NEUTRAL"], + value.summary["BUY"])) + if input("{}#7{} Are the results the same? (Y/N) ".format(Fore.BLUE, Style.RESET_ALL)).lower() == "y": + print("{}#7{} Multiple analysis test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, + Style.RESET_ALL)) + success += 1 + else: + print("{}#7{} Multiple analysis test {}failed{}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL)) +except Exception as e: + print("{}#7{} Multiple analysis test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, + Fore.RED, Style.RESET_ALL, e)) print("------------------------------------------------") print("Test finished. Result: {}{}/{}{}.".format(Fore.LIGHTWHITE_EX, success, COUNT, Style.RESET_ALL)) diff --git a/tradingview_ta/__init__.py b/tradingview_ta/__init__.py index 8ce1275..0397793 100644 --- a/tradingview_ta/__init__.py +++ b/tradingview_ta/__init__.py @@ -1,2 +1,3 @@ -from .main import TA_Handler, TradingView, Analysis, Interval, Exchange, get_multiple_analysis, __version__ +from .main import TA_Handler, TradingView, Analysis, Interval, Exchange, get_multiple_analysis, \ + get_multiple_analysis_with_multiple_intervals, __version__ from .technicals import Recommendation, Compute diff --git a/tradingview_ta/main.py b/tradingview_ta/main.py index bf70e74..029e39f 100644 --- a/tradingview_ta/main.py +++ b/tradingview_ta/main.py @@ -8,7 +8,7 @@ import requests -from technicals import Compute +from .technicals import Compute __version__ = "3.3.0" @@ -635,10 +635,4 @@ def get_multiple_analysis_with_multiple_intervals(screener, intervals, symbols, final[i.upper()].indicators = combain_dict - print(final["BINANCE:SOLUSDT"].indicators) return final - - -get_multiple_analysis_with_multiple_intervals(screener="crypto", - intervals=[Interval.INTERVAL_1_DAY, Interval.INTERVAL_1_HOUR], - symbols=["BINANCE:SOLUSDT"])