Skip to content

Commit fe3acd9

Browse files
Guillaume De Saint MartinGuillaumeDSM
Guillaume De Saint Martin
authored andcommitted
[Exchanges] fix kline parsing
1 parent 3d07892 commit fe3acd9

File tree

4 files changed

+53
-14
lines changed

4 files changed

+53
-14
lines changed

octobot_trading/exchanges/adapters/abstract_adapter.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ def adapt_ohlcv(self, raw, **kwargs):
4949
fixed = self.fix_ohlcv(raw, **kwargs)
5050
return self.parse_ohlcv(fixed, **kwargs)
5151

52+
@_adapter
53+
def adapt_kline(self, raw, **kwargs):
54+
fixed = self.fix_kline(raw, **kwargs)
55+
return self.parse_kline(fixed, **kwargs)
56+
5257
@_adapter
5358
def adapt_ticker(self, raw, **kwargs):
5459
fixed = self.fix_ticker(raw, **kwargs)
@@ -124,6 +129,13 @@ def fix_ohlcv(self, raw, **kwargs):
124129
def parse_ohlcv(self, fixed, **kwargs):
125130
raise NotImplementedError("parse_ohlcv is not implemented")
126131

132+
def fix_kline(self, raw, **kwargs):
133+
# add generic logic if necessary
134+
return raw
135+
136+
def parse_kline(self, fixed, **kwargs):
137+
raise NotImplementedError("parse_kline is not implemented")
138+
127139
def fix_ticker(self, raw, **kwargs):
128140
# add generic logic if necessary
129141
return raw

octobot_trading/exchanges/connectors/ccxt/ccxt_adapter.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import octobot_trading.enums as enums
2424
from octobot_trading.enums import ExchangeConstantsOrderColumns as ecoc
2525
import octobot_commons.enums as common_enums
26+
import octobot_commons.constants as common_constants
2627

2728

2829
class CCXTAdapter(adapters.AbstractAdapter):
@@ -41,14 +42,23 @@ def parse_order(self, fixed, **kwargs):
4142
fixed.pop(ecoc.INFO.value)
4243
return fixed
4344

45+
def _fix_ohlcv_prices(self, ohlcv):
46+
for index, value in enumerate(ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value + 1:]):
47+
ohlcv[index + 1] = float(value)
48+
4449
def fix_ohlcv(self, raw, **kwargs):
4550
fixed = super().fix_ohlcv(raw, **kwargs)
51+
# ensure open time is not the current time but the actual candle open time
52+
# time_frame kwarg has to be passed to parse candle time
53+
candles_s = 1
54+
if "time_frame" in kwargs:
55+
candles_s = common_enums.TimeFramesMinutes[common_enums.TimeFrames(kwargs["time_frame"])] * \
56+
common_constants.MINUTE_TO_SECONDS
4657
for ohlcv in fixed:
4758
try:
48-
ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value] = \
49-
int(self.get_uniformized_timestamp(ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value]))
50-
for index, value in enumerate(ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value + 1:]):
51-
ohlcv[index + 1] = float(value)
59+
int_val = int(self.get_uniformized_timestamp(ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value]))
60+
ohlcv[common_enums.PriceIndexes.IND_PRICE_TIME.value] = int_val - (int_val % candles_s)
61+
self._fix_ohlcv_prices(ohlcv)
5262
except KeyError as e:
5363
self.logger.error(f"Fail to fix ohlcv ({e})")
5464
return fixed
@@ -57,6 +67,21 @@ def parse_ohlcv(self, fixed, **kwargs):
5767
# CCXT standard ohlcv parsing logic
5868
return fixed
5969

70+
def fix_kline(self, raw, **kwargs):
71+
fixed = super().fix_kline(raw, **kwargs)
72+
for kline in fixed:
73+
try:
74+
kline[common_enums.PriceIndexes.IND_PRICE_TIME.value] = \
75+
int(self.get_uniformized_timestamp(kline[common_enums.PriceIndexes.IND_PRICE_TIME.value]))
76+
self._fix_ohlcv_prices(kline)
77+
except KeyError as e:
78+
self.logger.error(f"Fail to fix kline ({e})")
79+
return fixed
80+
81+
def parse_kline(self, fixed, **kwargs):
82+
# CCXT standard kline parsing logic
83+
return fixed
84+
6085
def fix_ticker(self, raw, **kwargs):
6186
fixed = super().fix_ticker(raw, **kwargs)
6287
# CCXT standard ticker fixing logic

octobot_trading/exchanges/connectors/ccxt/ccxt_connector.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,10 @@ async def get_kline_price(self,
211211
time_frame: octobot_commons.enums.TimeFrames,
212212
**kwargs: dict) -> typing.Optional[list]:
213213
try:
214-
# default implementation
215-
# already adapted in get_symbol_prices
216-
return await self.get_symbol_prices(symbol, time_frame, limit=1, **kwargs)
214+
with self.error_describer():
215+
return self.adapter.adapt_kline(
216+
await self.client.fetch_ohlcv(symbol, time_frame.value, limit=1, params=kwargs)
217+
)
217218
except ccxt.NotSupported:
218219
raise octobot_trading.errors.NotSupported
219220
except ccxt.BaseError as e:

octobot_trading/exchanges/connectors/ccxt/ccxt_websocket_connector.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ async def candle(self, candles: list, symbol=None, timeframe=None, **kwargs):
728728
:param kwargs: the feed kwargs
729729
"""
730730
time_frame = commons_enums.TimeFrames(timeframe)
731+
kline = self.adapter.adapt_kline([copy.deepcopy(candles[-1])])[0]
731732
adapted = self.adapter.adapt_ohlcv(candles, time_frame=time_frame)
732733
last_candle = adapted[-1]
733734
if symbol not in self.watched_pairs:
@@ -765,23 +766,23 @@ async def candle(self, candles: list, symbol=None, timeframe=None, **kwargs):
765766
trading_constants.KLINE_CHANNEL,
766767
time_frame,
767768
symbol,
768-
last_candle
769+
kline
769770
)
770771

771772
# Push a new ticker if necessary : only push on the min timeframe
772773
if time_frame is self.min_timeframe:
773774
ticker = {
774-
Ectc.HIGH.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_HIGH.value],
775-
Ectc.LOW.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_LOW.value],
775+
Ectc.HIGH.value: kline[commons_enums.PriceIndexes.IND_PRICE_HIGH.value],
776+
Ectc.LOW.value: kline[commons_enums.PriceIndexes.IND_PRICE_LOW.value],
776777
Ectc.BID.value: None,
777778
Ectc.BID_VOLUME.value: None,
778779
Ectc.ASK.value: None,
779780
Ectc.ASK_VOLUME.value: None,
780-
Ectc.OPEN.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_OPEN.value],
781-
Ectc.CLOSE.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_CLOSE.value],
782-
Ectc.LAST.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_CLOSE.value],
781+
Ectc.OPEN.value: kline[commons_enums.PriceIndexes.IND_PRICE_OPEN.value],
782+
Ectc.CLOSE.value: kline[commons_enums.PriceIndexes.IND_PRICE_CLOSE.value],
783+
Ectc.LAST.value: kline[commons_enums.PriceIndexes.IND_PRICE_CLOSE.value],
783784
Ectc.PREVIOUS_CLOSE.value: None,
784-
Ectc.BASE_VOLUME.value: last_candle[commons_enums.PriceIndexes.IND_PRICE_VOL.value],
785+
Ectc.BASE_VOLUME.value: kline[commons_enums.PriceIndexes.IND_PRICE_VOL.value],
785786
Ectc.TIMESTAMP.value: self.exchange.get_exchange_current_time(),
786787
}
787788
await self.push_to_channel(

0 commit comments

Comments
 (0)