ta-lib-python icon indicating copy to clipboard operation
ta-lib-python copied to clipboard

Different values (TradingView/Binance, ta-lib)

Open tratteo opened this issue 4 years ago • 21 comments

I am getting substantially different values from ta-lib with respect to both Binance and Trading view. All three indicators: STOCH, RSI, MACD return different values. Sometimes the difference is negligible, other times it goes as high as 10 points for the stochastic. What is causing this? Code for reference

import websocket, json, pprint, talib, numpy
import config
from binance.client import Client
from binance.enums import *
import time

SOCKET = "wss://stream.binance.com:9443/ws/ethusdt@kline_1m"
RSI_PERIOD = 14
TRADE_SYMBOL = 'ETHUSDT'
TRADE_QUANTITY = 0.005

macds = []
closes = []
highs = []
lows = []

is_long = False
client = Client(config.API_KEY, config.API_SECRET)
current_timestamp = round(time.time() * 1000)
print(current_timestamp)
val = current_timestamp - (200 * 60000)
hist = client.get_historical_klines(TRADE_SYMBOL, '1m', val, None, 200, HistoricalKlinesType.SPOT)

for a in hist:
    closes.append(float(a[4]))
    highs.append(float(a[2]))
    lows.append(float(a[3]))

def on_open(ws):
    print('opened connection')

def on_close(ws):
    print('closed connection')

def on_message_event(ws, message):
    json_message = json.loads(message)
    # pprint.pprint(json_message)
    candle = json_message['k']

    is_candle_closed = candle['x']
    close = candle['c']
    if is_candle_closed:
        print("candle closed at {}".format(candle))
        closes.append(float(close))
        highs.append(float(candle['h']))
        lows.append(float(candle['l']))
        np_closes = numpy.array(closes)
        macd, signal, hist = talib.MACD(np_closes)
        rsi = talib.RSI(np_closes, RSI_PERIOD)
        stoch_k, stoch_d = talib.STOCH(numpy.array(highs), numpy.array(lows), np_closes, fastk_period=14,
                                       slowk_period=1,
                                       slowd_period=3, slowk_matype=0, slowd_matype=0)
        print("Stochastic: [k, d] > [" + str(stoch_k[-1]) + ", " + str(stoch_d[-1]) + "]")
        print("RSI: " + str(rsi[-1]))
        print("MACD: [macd, sig] > [" + str(macd[-1]) + ", " + str(signal[-1]) + "]")

        # print("checking")
        # can = can_long(rsi, [macd, signal], [stoch_k, stoch_d])
        # if can:
        #     print("Long entered")


ws = websocket.WebSocketApp(SOCKET, on_open=on_open, on_close=on_close, on_message=on_message_event)
ws.run_forever()

tratteo avatar Oct 09 '21 18:10 tratteo

Imho, These are moving averages and they having "a memory". Their values today depends on what happened yesterday and so on. If you start one such moving average calculation since beginning of the year, and another (same function) will be calculated since the beginning of the month - you'll get the different results for today, depending on the size of moving window and how important is the past (weights of smoothing). Thus your function values will be different in a short term, but must converge in a long term. The question is: when TradingView/Binance have started their MACD etc. calculation? Start from the same point of historical data and then compare the results to minimize the influence of the memory. Or wait long enough to let your function results converge to their functions results.

trufanov-nok avatar Oct 09 '21 19:10 trufanov-nok

That’s typically the reason, another one might be use of different moving average types. TA-Lib supports 7 or 8 and many functions take that as a parameter.

On Oct 9, 2021, at 9:11 AM, Alexander Trufanov @.***> wrote:

 Imho, These are moving averages and they having "a memory". Their values today depends on what happened yesterday and so on. If you start one such moving average calculation since beginning of the year, and another (same function) will be calculated since the beginning of the month - you'll get the different results for today, depending on the size of moving window and how important is the past (weights of smoothing). Thus your function values will be different in a short term, but must converge in a long term. The question is: when TradingView/Binance have started their MACD etc. calculation? Start from the same point of historical data and then compare the results to minimize the influence of the memory. Or wait long enough to let your function results converge to their functions results.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

mrjbq7 avatar Oct 09 '21 19:10 mrjbq7

Thanks for the replies. It probably is simple a lack in my knowledge, however, if i set a certain period P for a certain indicator on Binance/TradingView, in a selected time frame, doesn't it mean that the indicator is calculated on that time frame using the last P candles? So if i set the same period P for the indicator and i calculate it over the same time frame in ta-lib, shouldn't they necessarily be the same? Where does the "memory" come from if i am using the period P and the indicator is calculated only by using the last P candles?

tratteo avatar Oct 10 '21 11:10 tratteo

Where does the "memory" come from

"memory" appears if your indicator uses it's own previous value for calculation. Like EMA:

EMA_Today=(Value_Today∗(Smoothing1+Days))+EMA_Yesterday∗(1−(Smoothing1+Days))

There is a good article that compares EMA and SMA (which is just a moving average like you would expect): https://www.investopedia.com/terms/e/ema.asp

And the MACD is "The MACD is calculated by subtracting the 26-period exponential moving average (EMA) from the 12-period EMA. (https://www.investopedia.com/terms/m/macd.asp)

The RSI formula can be found here: https://www.investopedia.com/terms/r/rsi.asp I guess memory come from "previous average gain" in RSI_step_two description.

And it seems STOCH is the one here who has no memory effect: https://www.investopedia.com/terms/s/stochasticoscillator.asp So you may doublecheck the STOCH

trufanov-nok avatar Oct 10 '21 11:10 trufanov-nok

Got it, however the stoch is the one that ouputs the most different values

tratteo avatar Oct 10 '21 13:10 tratteo

I am getting substantially different values from ta-lib with respect to both Binance and Trading view.

Are you sure they are displaying STOCH and not STOCHRSI? I couldn't find STOCH on Binance. TA-Lib has STOCHRSI indicator too. Perhaps you should use it instead of STOCH.

trufanov-nok avatar Oct 10 '21 13:10 trufanov-nok

I think it uses a moving average of period P with longer history in the calculation.

On Oct 10, 2021, at 4:16 AM, Matteo Beltrame @.***> wrote:

 Thanks for the replies. It probably is simple a lack in my knowledge, however, if i set a certain period P for a certain indicator on Binance/TradingView, in a selected time frame, doesn't it mean that the indicator is calculated on that time frame using the last P candles? So if i set the same period P for the indicator and i calculate it over the same time frame in ta-lib, shouldn't they necessarily be the same? Where does the "memory" come from if i am using the period P and the indicator is calculated only by using the last P candles?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

mrjbq7 avatar Oct 10 '21 16:10 mrjbq7

I am getting substantially different values from ta-lib with respect to both Binance and Trading view.

Are you sure they are displaying STOCH and not STOCHRSI? I couldn't find STOCH on Binance. TA-Lib has STOCHRSI indicator too. Perhaps you should use it instead of STOCH.

Well yes both on Binance and Trading view there are both the stochastic and the stochastic RSI, they have different values and ta-lib too has STOCH and STOCHRSI

tratteo avatar Oct 10 '21 17:10 tratteo

I've registered on Binance, opened any graphic, selected settings of currently displayed indicator and able to see only:

MA EMA WMA BOLL VWAP AVL TRIX SAR 
Sub (1/5)
VOL MACD RSI KDJ OBV CCI StochRSI WR DMI MTM EMV

And no STOCH...

trufanov-nok avatar Oct 10 '21 18:10 trufanov-nok

The chart must be in Trading View mode, on the top right corner of the chart

tratteo avatar Oct 10 '21 20:10 tratteo

The chart must be in Trading View mode, on the top right corner of the chart

Got it! So there is only one technical indicator to compare after all - the one that is built in by TradingView and shown by Binance. I'm comparing the 1m graphical data from https://www.binance.com/en/futures/ETHUSDT And the data I'm getting with the code:

import json
import numpy
import talib
import websocket


# *******PARAMETERS
# Name of Socket for BTC in USDT 1min Candle
SOCKET = "wss://stream.binance.com:9443/ws/ethusdt@kline_1m"
# Arrays
closes = []
highs = []
lows = []


def on_open_ws(ws):
    print('opened connection')

def on_close_ws(ws):
    print('closed connection')

def on_message_ws(ws, message):
    json_message = json.loads(message)
    # pprint.pprint(json_message)
    candle = json_message['k']

    is_candle_closed = candle['x']
    close = candle['c']
    if is_candle_closed:
        print("candle closed at {}".format(candle))
        closes.append(float(close))
        highs.append(float(candle['h']))
        lows.append(float(candle['l']))
        np_closes = numpy.array(closes)
        stoch_k, stoch_d = talib.STOCH(numpy.array(highs), numpy.array(lows), np_closes, fastk_period=14,
                                       slowk_period=1,
                                       slowd_period=3, slowk_matype=0, slowd_matype=0)
        print("Stochastic: [k, d] > [" + str(stoch_k[-1]) + ", " + str(stoch_d[-1]) + "]")

ws = websocket.WebSocketApp(SOCKET, on_open=on_open_ws, on_close=on_close_ws, on_message=on_message_ws)
ws.run_forever()

I'm observing STOCH mismatch, but I've also noticed that candle data mismatches too. Like I see 'c': '3606.60000000' for a latest candle while 3604.90 is on the trading view... Am I missing something? Could you reproduce that?

trufanov-nok avatar Oct 11 '21 09:10 trufanov-nok

You are checking the Binance futures while the code is running on Spot. Compare the code with the chart at: ETHUSDT. With this comparison i am getting a maximum error between the code and the chart of 0.2, in the closing price. I think that is neglegible. At this point having a maximum error of 0.2 (on multiple candles), why indicators are so different? (STOCH go as high as 10 points error, that is 10% error). And not only the STOCH, also the RSI and MACD.

tratteo avatar Oct 11 '21 12:10 tratteo

If you wait 40 min and compare STOCH again, wouldn't it be pretty same? It looks like mine is converged to the one on graphic. If it is so, I could dig into the code to try to explain this behavior.

trufanov-nok avatar Oct 11 '21 15:10 trufanov-nok

I also noticed that it tends to converge to the right values. However, i am asking myself why is that? I still don't understand as the indicators just depends on N previous candles, with N the max of the periods. How come that the values are so different? The only thing that comes to mind is that Binance indeed does some weird smoothing under the hood.

tratteo avatar Oct 11 '21 18:10 tratteo

Binance indeed does some weird smoothing under the hood.

I doubt so )

Could you execute following?:

import talib
talib.__ta_version__

from talib import abstract
stoch =  abstract.Function('stoch')
stoch.set_parameters(fastk_period=14, slowk_period=1, slowd_period=3, slowk_matype=0, slowd_matype=0)
stoch.lookback

I wonder which talib sources is under the hood of your wrapper and what lookback value it return.

trufanov-nok avatar Oct 12 '21 11:10 trufanov-nok

Version: b'0.4.0 (Sep 29 2020 17:46:20) Stoch.lookback: 15

tratteo avatar Oct 12 '21 19:10 tratteo

STOCH uses EMA which has a history, so of course it will converge over time, but be different if only considering "period" data points...

mrjbq7 avatar Oct 12 '21 19:10 mrjbq7

STOCH uses EMA which has a history, so of course it will converge over time, but be different if only considering "period" data points...

No, it's using lowk_matype=0, slowd_matype=0 which is SMA: https://sourceforge.net/p/ta-lib-git/code/ci/master/tree/ta-lib/c/include/ta_defs.h#l262. I've debugged the indicator step-by step on C side. I also run a few tests and now 100% sure STOCH with lowk_matype=0, slowd_matype=0 has no memory.

I finally found a setting that displays stoch arguments on binance graph - they are same: 14, 1, 3. Then I manually entered some data from the graph (13.10.2021 11:50 UTC - 12.05 UTC):

open  = [3459.47 , 3461.88 , 3459.25 , 3464.28 , 3466.38 , 3465.23 , 3466.79 , 3466.57 , 3467.91 , 3465.93 , 3468.67 , 3465.66 , 3469.43 , 3463.93 , 3469.36 , 3466.84]
high  = [3461.89 , 3462.03 , 3464.15 , 3467.94 , 3467.62 , 3466.80 , 3467.83 , 3468.48 , 3468.31 , 3469.04 , 3469.20 , 3472.76 , 3469.85 , 3469.67 , 3470.01 , 3470.00]
low   = [3458.76 , 3458.97 , 3457.69 , 3464.03 , 3464.55 , 3462.78 , 3466.11 , 3466.01 , 3465.55 , 3465.64 , 3464.32 , 3465.58 , 3462.65 , 3461.33 , 3466.82 , 3466.84]
close = [3461.89 , 3459.25 , 3463.76 , 3466.51 , 3465.32 , 3466.79 , 3466.57 , 3467.98 , 3465.83 , 3468.68 , 3465.65 , 3469.43 , 3463.93 , 3469.35 , 3466.82 , 3467.95]

stoch_k, stoch_d = talib.STOCH(numpy.array(high), numpy.array(low), numpy.array(close), fastk_period=14, slowk_period=1, slowd_period=3, slowk_matype=0, slowd_matype=0)

stoch_k is

array([        nan,         nan,         nan,         nan,         nan,
               nan,         nan,         nan,         nan,         nan,
               nan,         nan,         nan,         nan,         nan,
       68.08228268])

stoch_d is

array([        nan,         nan,         nan,         nan,         nan,
               nan,         nan,         nan,         nan,         nan,
               nan,         nan,         nan,         nan,         nan,
       68.67949569])

While the graph displays 68.0823 68.6795.

So the STOCH indicator is calculated correctly and it's exactly the same as Binance use. One may try himself with data after 12.05 UTC or another piece of data. Tips: write down only last 4 digits and add 3400 to them later. I also didn't notice that I don't need open prices from the beginning.

So, everything is fine with Binance and the indicator. The differences might be caused by incoming data fluctuations, or probably I don't see some problem in the python code (I'm not a python developer after all).

trufanov-nok avatar Oct 13 '21 13:10 trufanov-nok

Thats a very good background and investigation, thank you @trufanov-nok

mrjbq7 avatar Oct 13 '21 15:10 mrjbq7

Any luck here ? Mine RSI value coming different from binance

import numpy import redis import tulipy as ti from talib import stream import time r = redis.StrictRedis( host='localhost', port=6379, connection_pool=None, db=0, decode_responses=True)

while True: candles = r.lrange("FETUSDT", -15, -1) y = [] for candle in candles: y.append(float(candle.split(',')[3]))

if len(y) > 0
	y = numpy.array(y)
	latest = stream.RSI(y)

	print("FETUSDT",latest)
time.sleep(2)
Screenshot 2021-11-13 at 11 07 13 PM Screenshot 2021-11-13 at 11 07 28 PM

DILIPSKUMAR1410 avatar Nov 13 '21 17:11 DILIPSKUMAR1410

Any luck here ? Mine RSI value coming different from binance

import numpy import redis import tulipy as ti from talib import stream import time r = redis.StrictRedis( host='localhost', port=6379, connection_pool=None, db=0, decode_responses=True)

while True: candles = r.lrange("FETUSDT", -15, -1) y = [] for candle in candles: y.append(float(candle.split(',')[3]))

if len(y) > 0
	y = numpy.array(y)
	latest = stream.RSI(y)

	print("FETUSDT",latest)
time.sleep(2)
Screenshot 2021-11-13 at 11 07 13 PM Screenshot 2021-11-13 at 11 07 28 PM

Any luck here?

DILIPSKUMAR1410 avatar Nov 22 '21 13:11 DILIPSKUMAR1410