I'm trying to write a program that will stream candlestick data from MT5. The logic of the program should be:
- Download 72 1-minute candles worth of data for BTCUSD.
- Check the terminal every 10 seconds to see if a new 1 minute candle has finished forming.
- If a new candle has formed, add it to the end of the 72 candle dataframe and delete the oldest index (I haven't coded the deletion part).
import MetaTrader5 as mt5
import pandas as pd
from pandas.testing import assert_frame_equal
import time
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1500)
if not mt5.initialize(): # start mt5
print("initialize failed")
mt5.shutdown()
account="HIDDEN" # account info to log into broker
authorized=mt5.login(account, server="HIDDEN")
if authorized:
print("Authorized")
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
# download last 72 bars of BTCUSD
cndl_72 = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 72)
cndl_72_df = pd.DataFrame(cndl_72) # convert to DataFrame
cndl_72_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s') # some time conversion thing from the documentation I don't really get it
while True: # start the stream
cndl_last = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 1) # download latest bar
cndl_last_df = pd.DataFrame(cndl_last) # convert to DataFrame
cndl_last_df['time']=pd.to_datetime(cndl_last_df['time'], unit='s') # do necessary time conversion
cndl_72_last_df = pd.DataFrame(cndl_72_df.iloc[-1]) # find the last index of the 72 candle dataframe
cndl_72_last_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s') # perform necessary time conversion
# check if the most recent bar is the same as the most recent entry in cndl_72_df
try:
assert_frame_equal([cndl_last_df, cndl_72_last_df])
print("True", cndl_last_df, cndl_72_last_df) # printing both just for testing purposes. produces bad output seen below.
except:
print("False", cndl_last_df, cndl_72_last_df)
pd.concat([cndl_72_df, cndl_last_df]) # append latest candle to the end of the 72 candle dataframe
print(cndl_72_df) # prints the edited 72 candle data frame, which doesn't show any changes as it should
time.sleep(10)
The output is:
Authorized
False time open high low close tick_volume spread real_volume
0 2022-02-21 02:10:00 38341.52 38362.1 38333.09 38347.18 65 900 0 71 time
time 2022-02-21 02:10:00 NaT
open 38341.52 NaT
high 38362.1 NaT
low 38333.09 NaT
close 38347.18 NaT
tick_volume 65 NaT
spread 900 NaT
real_volume 0 NaT
time open high low close tick_volume spread real_volume
0 2022-02-21 00:59:00 38868.19 38936.00 38809.08 38936.00 57 900 0
1 2022-02-21 01:00:00 38933.90 38988.80 38889.51 38928.32 170 900 0
2 2022-02-21 01:01:00 38927.82 38936.33 38826.26 38874.85 153 1460 0
3 2022-02-21 01:02:00 38875.26 38891.40 38789.51 38798.90 160 2431 0
4 2022-02-21 01:03:00 38804.90 38811.40 38688.26 38707.40 125 1371 0
.. ... ... ... ... ... ... ... ...
67 2022-02-21 02:06:00 38263.27 38276.48 38217.98 38229.26 63 900 0
68 2022-02-21 02:07:00 38220.48 38341.98 38211.98 38305.03 79 900 0
69 2022-02-21 02:08:00 38308.01 38309.77 38263.59 38295.85 81 900 0
70 2022-02-21 02:09:00 38292.76 38339.90 38281.08 38338.51 71 900 0
71 2022-02-21 02:10:00 38341.52 38362.10 38333.09 38347.18 65 900 0
[72 rows x 8 columns]
False time open high low close tick_volume spread real_volume
0 2022-02-21 02:10:00 38341.52 38362.1 38333.09 38347.18 65 900 0 71 time
time 2022-02-21 02:10:00 NaT
open 38341.52 NaT
high 38362.1 NaT
low 38333.09 NaT
close 38347.18 NaT
tick_volume 65 NaT
spread 900 NaT
real_volume 0 NaT
time open high low close tick_volume spread real_volume
0 2022-02-21 00:59:00 38868.19 38936.00 38809.08 38936.00 57 900 0
1 2022-02-21 01:00:00 38933.90 38988.80 38889.51 38928.32 170 900 0
2 2022-02-21 01:01:00 38927.82 38936.33 38826.26 38874.85 153 1460 0
3 2022-02-21 01:02:00 38875.26 38891.40 38789.51 38798.90 160 2431 0
4 2022-02-21 01:03:00 38804.90 38811.40 38688.26 38707.40 125 1371 0
.. ... ... ... ... ... ... ... ...
67 2022-02-21 02:06:00 38263.27 38276.48 38217.98 38229.26 63 900 0
68 2022-02-21 02:07:00 38220.48 38341.98 38211.98 38305.03 79 900 0
69 2022-02-21 02:08:00 38308.01 38309.77 38263.59 38295.85 81 900 0
70 2022-02-21 02:09:00 38292.76 38339.90 38281.08 38338.51 71 900 0
71 2022-02-21 02:10:00 38341.52 38362.10 38333.09 38347.18 65 900 0
[72 rows x 8 columns]
False time open high low close tick_volume spread real_volume
0 2022-02-21 02:10:00 38341.52 38362.1 38333.09 38347.18 65 900 0 71 time
time 2022-02-21 02:10:00 NaT
open 38341.52 NaT
high 38362.1 NaT
low 38333.09 NaT
close 38347.18 NaT
tick_volume 65 NaT
spread 900 NaT
real_volume 0 NaT
time open high low close tick_volume spread real_volume
0 2022-02-21 00:59:00 38868.19 38936.00 38809.08 38936.00 57 900 0
1 2022-02-21 01:00:00 38933.90 38988.80 38889.51 38928.32 170 900 0
2 2022-02-21 01:01:00 38927.82 38936.33 38826.26 38874.85 153 1460 0
3 2022-02-21 01:02:00 38875.26 38891.40 38789.51 38798.90 160 2431 0
4 2022-02-21 01:03:00 38804.90 38811.40 38688.26 38707.40 125 1371 0
.. ... ... ... ... ... ... ... ...
67 2022-02-21 02:06:00 38263.27 38276.48 38217.98 38229.26 63 900 0
68 2022-02-21 02:07:00 38220.48 38341.98 38211.98 38305.03 79 900 0
69 2022-02-21 02:08:00 38308.01 38309.77 38263.59 38295.85 81 900 0
70 2022-02-21 02:09:00 38292.76 38339.90 38281.08 38338.51 71 900 0
71 2022-02-21 02:10:00 38341.52 38362.10 38333.09 38347.18 65 900 0
As you can see the try/except repeatedly tests false which shouldn't happen. If the most recent candle is downloaded, the output should be True, and when the program detects a new candle the output should be False.
This question is a continuation of this question I asked earlier: Compare Last Index of a Dataframe with a Single Index Dataframe
In an attempt to solve my own problem I made numerous changes to the code. The question became harder and harder for the public to answer as I kept making changes and new issues started arising. This question was created in an attempt to make things less confusing.
EDIT #1, new code with changes as suggested:
import MetaTrader5 as mt5
import pandas as pd
import time
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1500)
if not mt5.initialize(): # start mt5
print("initialize failed")
mt5.shutdown()
account="HIDDEN" # account info to log into broker
authorized=mt5.login(account, server="HIDDEN")
if authorized:
print("Authorized")
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
# download last 10 bars of BTCUSD
cndl_72 = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 72)
cndl_72_df = pd.DataFrame(cndl_72) # convert to DataFrame
cndl_72_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s') # some time conversion thing from the documentation I don't really get it
while True: # start the stream
cndl_last = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 1) # download latest bar
cndl_last_df = pd.DataFrame(cndl_last) # convert to DataFrame
cndl_last_df['time']=pd.to_datetime(cndl_last_df['time'], unit='s') # do necessary time conversion
cndl_72_last_df = (cndl_72_df.iloc[-1]).to_frame()
#below line throws an error.
cndl_72_last_df['time']=pd.to_datetime(cndl_72_last_df['time'], unit='s')
# check if the most recent bar is the same as the most recent entry in bars_frame
if cndl_last_df.equals(cndl_72_last_df):
print("True", cndl_last_df, cndl_72_last_df)
else:
print("False", cndl_last_df, cndl_72_last_df)
cndl_72_df = pd.concat([cndl_72_df, cndl_last_df])
print(cndl_72_df)
time.sleep(10)
new code throws this error:
Authorized
Traceback (most recent call last):
File "C:\Users\hello\Documents\projects\alerter_venv\lib\site-packages\pandas\core\indexes\base.py", line 3621, in get_loc
return self._engine.get_loc(casted_key)
File "pandas\_libs\index.pyx", line 136, in pandas._libs.index.IndexEngine.get_loc
File "pandas\_libs\index.pyx", line 144, in pandas._libs.index.IndexEngine.get_loc
File "pandas\_libs\index_class_helper.pxi", line 41, in pandas._libs.index.Int64Engine._check_type
KeyError: 'time'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\hello\Documents\projects\alerter_venv\main_2.py", line 31, in <module>
cndl_72_last_df['time']=pd.to_datetime(cndl_72_last_df['time'], unit='s')
File "C:\Users\hello\Documents\projects\alerter_venv\lib\site-packages\pandas\core\frame.py", line 3505, in __getitem__
indexer = self.columns.get_loc(key)
File "C:\Users\hello\Documents\projects\alerter_venv\lib\site-packages\pandas\core\indexes\base.py", line 3623, in get_loc
raise KeyError(key) from err
KeyError: 'time'
EDIT #2: new code with suggestions:
import MetaTrader6 as mt5
import pandas as pd
import time
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1500)
if not mt5.initialize(): # start mt5
print("initialize failed")
mt5.shutdown()
account="HIDDEN" # account info to log into broker
authorized=mt5.login(account, server="HIDDEN")
if authorized:
print("Authorized")
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
# download last 10 bars of BTCUSD
cndl_72 = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 72)
cndl_72_df = pd.DataFrame(cndl_72) # convert to DataFrame
cndl_72_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s') # some time conversion thing from the documentation I don't really get it
while True: # start the stream
cndl_last = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 1) # download latest bar
cndl_last_df = pd.DataFrame(cndl_last) # convert to DataFrame
cndl_last_df['time']=pd.to_datetime(cndl_last_df['time'], unit='s') # do necessary time conversion
cndl_72_last_df = cndl_72_df.iloc[[-1]]
#below line throws an error.
cndl_72_last_df['time']=pd.to_datetime(cndl_72_last_df['time'], unit='s')
# check if the most recent bar is the same as the most recent entry in bars_frame
if cndl_last_df.iloc[[-1]].reset_index(drop=True)\
.equals(cndl_72_last_df):
print("True", cndl_last_df, cndl_72_last_df)
else:
print("False", cndl_last_df, cndl_72_last_df)
cndl_72_df = pd.concat([cndl_72_df, cndl_last_df])
print(cndl_72_df)
time.sleep(10)
Errors below:
Authorized
C:\Users\hello\Documents\projects\alerter_venv\main_2.py:31: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
cndl_72_last_df['time']=pd.to_datetime(cndl_72_last_df['time'], unit='s')
False time open high low close tick_volume spread real_volume
0 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0 time open high low close tick_volume spread real_volume
71 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0
time open high low close tick_volume spread real_volume
0 2022-02-21 13:25:00 38326.97 38352.76 38295.47 38296.97 60 900 0
1 2022-02-21 13:26:00 38294.47 38312.76 38273.47 38274.97 56 900 0
2 2022-02-21 13:27:00 38274.26 38275.97 38231.97 38266.47 85 900 0
3 2022-02-21 13:28:00 38269.26 38307.47 38231.97 38286.47 81 900 0
4 2022-02-21 13:29:00 38284.51 38295.47 38258.47 38281.51 62 900 0
.. ... ... ... ... ... ... ... ...
68 2022-02-21 14:33:00 37648.50 37663.51 37633.00 37642.00 54 900 0
69 2022-02-21 14:34:00 37642.00 37653.26 37611.00 37632.00 54 900 0
70 2022-02-21 14:35:00 37634.50 37636.00 37611.50 37613.11 67 900 0
71 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0
0 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0
[73 rows x 8 columns]
C:\Users\hello\Documents\projects\alerter_venv\main_2.py:31: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
cndl_72_last_df['time']=pd.to_datetime(cndl_72_last_df['time'], unit='s')
True time open high low close tick_volume spread real_volume
0 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0 time open high low close tick_volume spread real_volume
0 2022-02-21 14:36:00 37615.11 37625.11 37581.61 37591.61 65 900 0
Traceback (most recent call last):
File "C:\Users\hello\Documents\projects\alerter_venv\main_2.py", line 42, in <module>
time.sleep(10)
KeyboardInterrupt
Index that is concatenated onto cndl_72_df is not 72 but shows 0 instead, and in the output index 72 and 0 are the same. The newest candle data should become index 72 with index 0 being deleted.
EDIT #3: code:
import MetaTrader5 as mt5
import pandas as pd
import time
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1500)
if not mt5.initialize(): # start mt5
print("initialize failed")
mt5.shutdown()
account="FOO" # account info to log into broker
authorized=mt5.login(account, server="FOO")
if authorized:
print("Authorized")
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
# download last 10 bars of EURUSD
cndl_72 = mt5.copy_rates_from_pos("EURUSD", mt5.TIMEFRAME_M1, 1, 72)
cndl_72_df = pd.DataFrame(cndl_72) # convert to DataFrame
cndl_72_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s') # some time conversion thing from the documentation I don't really get it
while True: # start the stream
cndl_last = mt5.copy_rates_from_pos("EURUSD", mt5.TIMEFRAME_M1, 1, 1) # download latest bar
cndl_last_df = pd.DataFrame(cndl_last) # convert to DataFrame
cndl_last_df['time']=pd.to_datetime(cndl_last_df['time'], unit='s') # do necessary time conversion
cndl_72_last_df = cndl_72_df.iloc[[-1]]
# check if the most recent bar is the same as the most recent entry in bars_frame
if cndl_72_last_df.equals(cndl_last_df):
print("True", cndl_last_df, cndl_72_last_df)
else:
print("False", cndl_last_df, cndl_72_last_df)
cndl_72_df = pd.concat([cndl_72_df, cndl_last_df])
#remove the oldest candle data:
cndl_72_df.drop(index=cndl_72_df.index[0], axis=0, inplace=True)
"""
Renumber the indexes so that the oldest index (now 1) becomes
0 and the rest follow until the last is 71. In the output you can
see that this expected behavior is not happening:
"""
cndl_72_df.reset_index(drop=True)
print(cndl_72_df)
time.sleep(10)
output:
Authorized
False time open high low close tick_volume spread real_volume
0 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0 time open high low close tick_volume spread real_volume
71 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
time open high low close tick_volume spread real_volume
1 2022-02-21 16:31:00 38557.01 38557.01 38462.59 38475.74 100 900 0
2 2022-02-21 16:32:00 38475.80 38590.34 38458.37 38578.34 95 1683 0
3 2022-02-21 16:33:00 38579.34 38615.44 38551.99 38557.46 101 959 0
4 2022-02-21 16:34:00 38562.46 38592.26 38486.15 38513.26 78 900 0
5 2022-02-21 16:35:00 38517.76 38638.82 38513.26 38525.46 100 900 0
.. ... ... ... ... ... ... ... ...
67 2022-02-21 17:37:00 38834.26 38852.51 38805.41 38833.76 81 900 0
68 2022-02-21 17:38:00 38836.08 38909.58 38836.08 38909.58 62 900 0
69 2022-02-21 17:39:00 38906.08 39015.11 38903.76 38972.61 104 900 0
70 2022-02-21 17:40:00 38986.11 39001.61 38929.61 38929.61 70 900 0
71 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
[71 rows x 8 columns]
False time open high low close tick_volume spread real_volume
0 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0 time open high low close tick_volume spread real_volume
71 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
time open high low close tick_volume spread real_volume
2 2022-02-21 16:32:00 38475.80 38590.34 38458.37 38578.34 95 1683 0
3 2022-02-21 16:33:00 38579.34 38615.44 38551.99 38557.46 101 959 0
4 2022-02-21 16:34:00 38562.46 38592.26 38486.15 38513.26 78 900 0
5 2022-02-21 16:35:00 38517.76 38638.82 38513.26 38525.46 100 900 0
6 2022-02-21 16:36:00 38527.46 38539.46 38478.96 38511.96 87 900 0
.. ... ... ... ... ... ... ... ...
68 2022-02-21 17:38:00 38836.08 38909.58 38836.08 38909.58 62 900 0
69 2022-02-21 17:39:00 38906.08 39015.11 38903.76 38972.61 104 900 0
70 2022-02-21 17:40:00 38986.11 39001.61 38929.61 38929.61 70 900 0
71 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
0 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
[71 rows x 8 columns]
True time open high low close tick_volume spread real_volume
0 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0 time open high low close tick_volume spread real_volume
0 2022-02-21 17:41:00 38930.11 38970.86 38914.11 38952.79 77 900 0
Traceback (most recent call last):
File "C:\Users\hello\Documents\projects\alerter_venv\main_2.py", line 42, in <module>
time.sleep(10)
KeyboardInterrupt
In this third edit I made 2 additional changes under the else:
statement which should delete the oldest index in the dataframe and renumber all of the indexes. As you can see the issues in the output are:
- Indexes aren't being renumbered correctly because you can see index 0 at the end of one of the dataframes, whereas it should always be index 71.
- I'm guessing the interpreter is evaluating 2 of the same candles with different indexes as being different even though its the same candle, which is why False is testing twice and a duplicate candle gets added.
CodePudding user response:
- It should not pass your
assert_frame_equal
test if you are really downloading new data. From the doc, its purpose is to:
Check that left and right DataFrame are equal.
which means that it will raise an AssertionError if the check fails. If you are downloading new data, you should expect for a different dataframe than before, and then you should expect the dataframe to be not equal, and so you should expect for an AssertionError.
pd.concat([cndl_72_df, cndl_last_df])
is not an inplace concat, meaning you need to assign the outcome of it to a variable in order to store that outcome. You therefore needcndl_72_df = pd.concat([cndl_72_df, cndl_last_df])
assert_frame_equal
is more for a test environment, you may instead use pd.DataFrame.equals to compare two dataframes, it will either give you a True or a False as return. E.gdf1.equals(df2)
I suppose you expect your
cndl_last_df
to grow on new data, therefore there is no point for you to compare ifcndl_last_df
andcndl_72_last_df
are the same, right? Because they should not be the same right? If so, you need to ask yourself what attributes fromcndl_72_last_df
should not repeat incndl_last_df
?
UPDATE
From your comment
The objective is to find the latest candlestick in cndl_72_df and see if it is the same as the most recent candlestick from MT5
We can pick the last row by cndl_72_df.iloc[[-1]]
cndl_72_last_df = cndl_72_df.iloc[[-1]].reset_index(drop=True)
and instead do
assert_frame_equal([cndl_last_df, cndl_72_last_df])
However, as explained, I would prefer
cndl_72_last_df.equals(cndl_last_df)
but that will require to remove the try-except block and rewrite things in a if-else block. So this is just for your consideration.
Note:
the inner bracket in
iloc
lets it return a DataFrame instead of a Series, and we need that becausecndl_last_df
is a DataFrame.reset_index
makes sure the index ofcndl_72_last_df
starts from zero, which is whatcndl_last_df
is supposed to be.Both dataframe should have the same set of columns and in the same order. I assume they are true as they are retrieved from the same source.
CodePudding user response:
Working code:
import MetaTrader5 as mt5
import pandas as pd
import time
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1500)
if not mt5.initialize():
print("initialize failed")
mt5.shutdown()
account="HIDDEN"
authorized=mt5.login(account, server="HIDDEN")
if authorized:
print("Authorized")
else:
print("failed to connect at account #{}, error code: {}".format(account, mt5.last_error()))
cndl_72 = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 5)
cndl_72_df = pd.DataFrame(cndl_72)
cndl_72_df['time']=pd.to_datetime(cndl_72_df['time'], unit='s')
while True: # start the stream
cndl_last = mt5.copy_rates_from_pos("BTCUSD", mt5.TIMEFRAME_M1, 1, 1) # download latest bar
cndl_last_df = pd.DataFrame(cndl_last) # convert to DataFrame
cndl_last_df['time']=pd.to_datetime(cndl_last_df['time'], unit='s') # do necessary time conversion
cndl_72_last_df = cndl_72_df.iloc[[-1]].reset_index(drop=True)
if cndl_72_last_df.equals(cndl_last_df):
print("Already on most recent candle.")
else:
print("New candle found.\n")
cndl_72_df = pd.concat([cndl_72_df, cndl_last_df])
cndl_72_df.reset_index(drop=True, inplace=True)
cndl_72_df.drop(index=cndl_72_df.index[0], axis=0, inplace=True)
cndl_72_df.reset_index(drop=True, inplace=True)
print(cndl_72_df)
time.sleep(10)
Output:
Authorized
Already on most recent candle.
Already on most recent candle.
Already on most recent candle.
New candle found.
time open high low close tick_volume spread real_volume
0 2022-02-21 21:14:00 37814.26 37825.26 37783.26 37818.76 61 949 0
1 2022-02-21 21:15:00 37818.76 37842.76 37741.10 37765.26 81 900 0
2 2022-02-21 21:16:00 37773.26 37779.26 37662.26 37671.26 125 900 0
3 2022-02-21 21:17:00 37658.26 37769.76 37657.76 37719.12 99 900 0
4 2022-02-21 21:18:00 37721.17 37811.85 37715.22 37775.01 101 900 0
Already on most recent candle.
Already on most recent candle.
Already on most recent candle.
Already on most recent candle.
Already on most recent candle.
New candle found.
time open high low close tick_volume spread real_volume
0 2022-02-21 21:15:00 37818.76 37842.76 37741.10 37765.26 81 900 0
1 2022-02-21 21:16:00 37773.26 37779.26 37662.26 37671.26 125 900 0
2 2022-02-21 21:17:00 37658.26 37769.76 37657.76 37719.12 99 900 0
3 2022-02-21 21:18:00 37721.17 37811.85 37715.22 37775.01 101 900 0
4 2022-02-21 21:19:00 37775.85 37778.85 37735.35 37759.51 70 900 0
Already on most recent candle.
Already on most recent candle.