Skip to content

Commit

Permalink
#11 Show number of trades for each coin (#12)
Browse files Browse the repository at this point in the history
pantunes authored Jan 1, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent d6cee80 commit 79cca65
Showing 8 changed files with 89 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .envs/.local/.rabbitmq
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
RABBITMQ_EXCHANGE=
RABBITMQ_EXCHANGE=amq.direct
RABBITMQ_HOST=rabbitmq
RABBITMQ_PORT=5672
RABBITMQ_TRADES_QUEUE_NAME=Trades
10 changes: 5 additions & 5 deletions exchange_radar/consumer/main.py
Original file line number Diff line number Diff line change
@@ -41,11 +41,11 @@ def callback(
properties: pika.BasicProperties,
body: bytes,
):
logger.info("CALLB")
logger.info("CONSUMER - start")

data = json.loads(body)

logger.info(f"DATA: {str(data)[:128]}")
logger.info(f"CONSUMER - data: {str(data)[:128]}")

requests.post(
self.url.format(coin=data["trade_symbol"]),
@@ -55,12 +55,12 @@ def callback(

ch.basic_ack(delivery_tag=method.delivery_tag)

logger.info("CALLB OK")
logger.info("CONSUMER - end")


def setup_channel(channel: BlockingChannel, queue_name: str, callback: Callable):
channel.queue_declare(queue=queue_name, durable=True)
channel.queue_bind(queue=queue_name, exchange="amq.direct")
channel.queue_bind(queue=queue_name, exchange=settings.RABBITMQ_EXCHANGE)
channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue=queue_name, on_message_callback=callback)

@@ -121,6 +121,6 @@ def main():
except AMQPConnectionError:
logger.error("ERROR: General AMQP Connection Error")
except Exception as error:
logger.error(f"ERROR: {error}")
logger.error(f"GENERAL ERROR: {error}")
finally:
sleep(ITER_SLEEP)
6 changes: 3 additions & 3 deletions exchange_radar/producer/publisher.py
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):


def publish(data: CustomBaseModel) -> None:
logger.info(f"PUB: {data.trade_time} {data.symbol}") # noqa
logger.info(f"PRODUCER - start: {data.trade_time} {data.symbol}") # noqa

try:
with ProducerChannel(queue_name=settings.RABBITMQ_TRADES_QUEUE_NAME) as channel:
@@ -113,6 +113,6 @@ def publish(data: CustomBaseModel) -> None:
except AMQPConnectionError:
logger.error("ERROR: General AMQP Connection Error")
except Exception as error:
logger.error(f"ERROR: {error}")
logger.error(f"GENERAL ERROR: {error}")
else:
logger.info(f"PUB OK: {data.trade_time} {data.symbol}") # noqa
logger.info(f"PRODUCER - end: {data.trade_time} {data.symbol}") # noqa
23 changes: 22 additions & 1 deletion exchange_radar/producer/schemas/base.py
Original file line number Diff line number Diff line change
@@ -39,9 +39,30 @@ def trade_symbol(self) -> str:
def volume(self) -> float:
today_date = datetime.today().date().strftime("%Y-%m-%d")
return _redis.hincrbyfloat(
today_date, self.trade_symbol, float(self.quantity) # noqa
today_date, f"{self.trade_symbol}_VOLUME", float(self.quantity) # noqa
)

@computed_field
def number_trades(self) -> tuple[int, int]:
today_date = datetime.today().date().strftime("%Y-%m-%d")

if self.is_seller is False: # noqa
num_buy_orders = _redis.hincrby(
today_date, f"{self.trade_symbol}_NUMBER_TRADES_BUY_ORDERS", 1
)
num_sell_orders = _redis.hget(
today_date, f"{self.trade_symbol}_NUMBER_TRADES_SELL_ORDERS"
)
else:
num_buy_orders = _redis.hget(
today_date, f"{self.trade_symbol}_NUMBER_TRADES_BUY_ORDERS"
)
num_sell_orders = _redis.hincrby(
today_date, f"{self.trade_symbol}_NUMBER_TRADES_SELL_ORDERS", 1
)

return num_buy_orders, num_sell_orders

@field_validator("trade_time", mode="after", check_fields=False)
def trade_time_after(cls, v) -> datetime:
return v.replace(microsecond=0)
2 changes: 1 addition & 1 deletion exchange_radar/producer/tasks/binance.py
Original file line number Diff line number Diff line change
@@ -33,4 +33,4 @@ async def process(self, symbol_or_symbols: str | tuple):
data = BinanceTradeSchema(**res)
publish(data) # noqa
except Exception as error:
logger.error(f"ERROR: {error}")
logger.error(f"GENERAL ERROR: {error}")
2 changes: 1 addition & 1 deletion exchange_radar/producer/tasks/coinbase.py
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ def on_message(self, message):
)
break
except Exception as error:
logger.error(f"ERROR: {error}")
logger.error(f"GENERAL ERROR: {error}")
logger.error(f"Trying again in {ITER_SLEEP} seconds...")
time.sleep(ITER_SLEEP)

24 changes: 24 additions & 0 deletions exchange_radar/producer/tests/test_schemas.py
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@
@patch("exchange_radar.producer.schemas.base._redis")
def test_schemas_binance(mock_redis):
mock_redis.hincrbyfloat.return_value = Decimal("100.0")
mock_redis.hincrby.return_value = 1
mock_redis.hget.return_value = 1

msg = {
"e": "trade", # Event type
@@ -41,6 +43,10 @@ def test_schemas_binance(mock_redis):
" 100.00000000 BNB | 0.10000000 BTC",
"message_with_keys": "2022-12-31 19:43:02 | Binance | PRICE: 0.00100000 BTC |"
" QTY: 100.00000000 BNB | TOTAL: 0.10000000 BTC",
"number_trades": (
1,
1,
),
"exchange": "Binance",
"volume": Decimal("100.0"),
}
@@ -49,6 +55,8 @@ def test_schemas_binance(mock_redis):
@patch("exchange_radar.producer.schemas.base._redis")
def test_schemas_kucoin(mock_redis):
mock_redis.hincrbyfloat.return_value = Decimal("3.7335")
mock_redis.hincrby.return_value = 1
mock_redis.hget.return_value = 1

msg = {
"type": "message",
@@ -82,6 +90,10 @@ def test_schemas_kucoin(mock_redis):
" 3.73350000 LTO | 0.00001313 BTC",
"message_with_keys": "2023-05-03 10:10:39 | Kucoin | PRICE: 0.00000352 BTC |"
" QTY: 3.73350000 LTO | TOTAL: 0.00001313 BTC",
"number_trades": (
1,
1,
),
"is_seller": True,
"exchange": "Kucoin",
"volume": Decimal("3.7335"),
@@ -91,6 +103,8 @@ def test_schemas_kucoin(mock_redis):
@patch("exchange_radar.producer.schemas.base._redis")
def test_schemas_coinbase(mock_redis):
mock_redis.hincrbyfloat.return_value = Decimal("0.00251665")
mock_redis.hincrby.return_value = 1
mock_redis.hget.return_value = 1

msg = {
"type": "last_match",
@@ -119,6 +133,10 @@ def test_schemas_coinbase(mock_redis):
" 0.00251665 ETH | 4.86702493 USD",
"message_with_keys": "2023-07-16 12:19:57 | Coinbase | PRICE: 1933.93000000 USD |"
" QTY: 0.00251665 ETH | TOTAL: 4.86702493 USD",
"number_trades": (
1,
1,
),
"is_seller": True,
"exchange": "Coinbase",
"volume": Decimal("0.00251665"),
@@ -128,6 +146,8 @@ def test_schemas_coinbase(mock_redis):
@patch("exchange_radar.producer.schemas.base._redis")
def test_schemas_kraken(mock_redis):
mock_redis.hincrbyfloat.return_value = Decimal("0.03409475")
mock_redis.hincrby.return_value = 1
mock_redis.hget.return_value = 1

msg = [
337,
@@ -161,6 +181,10 @@ def test_schemas_kraken(mock_redis):
" 0.03409475 BTC | 1019.81488620 USD",
"message_with_keys": "2023-07-23 12:23:40 | Kraken | PRICE: 29911.20000000 USD |"
" QTY: 0.03409475 BTC | TOTAL: 1019.81488620 USD",
"number_trades": (
1,
1,
),
"is_seller": True,
"exchange": "Kraken",
"volume": Decimal("0.03409475"),
52 changes: 32 additions & 20 deletions exchange_radar/web/templates/base.html
Original file line number Diff line number Diff line change
@@ -55,8 +55,8 @@

function setVolume(obj) {
const volume = obj.volume.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
minimumFractionDigits: 8,
maximumFractionDigits: 8
});
$(`#${obj.trade_symbol}_volume`).text(volume);

@@ -67,6 +67,11 @@
$(`#${obj.trade_symbol}_volume_in_currency`).text(`${volume_in_currency} ${obj.currency}`);
}

function setNumberTrades(obj) {
$(`#${obj.trade_symbol}_number_trades_buy_orders`).text(obj.number_trades[0]);
$(`#${obj.trade_symbol}_number_trades_sell_orders`).text(obj.number_trades[1]);
}

function retrieveData() {
$.get('{{ http_url }}').done(function (response) {
for (const obj of response.r) {
@@ -92,6 +97,7 @@
setPageTitle(obj);
addRow(obj);
setVolume(obj);
setNumberTrades(obj);
}

ws.onclose = function(e) {
@@ -176,61 +182,67 @@


<b>Bitcoin:</b>
{%- if coin == "BTC" %}
<i>Daily Volume: <span id="BTC_volume">-</span> BTC @ <span id="BTC_volume_in_currency">-</span></i>
{%- endif %}

<a href="/BTC">BTC all trades</a>
{%- if coin == "BTC" %}
<i>Daily Volume: <span id="BTC_volume">-</span> BTC @ <span id="BTC_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="BTC_number_trades_buy_orders">-</span>, Sells <span id="BTC_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/BTC/octopuses">BTC octopus trades</a>
<a href="/BTC/dolphins">BTC dolphin trades</a> 💾
<a href="/BTC/whales">BTC whale trades</a> 💾

<b>Ethereum:</b>
{%- if coin == "ETH" %}
<i>Daily Volume: <span id="ETH_volume">-</span> ETH @ <span id="ETH_volume_in_currency">-</span></i>
{%- endif %}

<a href="/ETH">ETH all trades</a>
{%- if coin == "ETH" %}
<i>Daily Volume: <span id="ETH_volume">-</span> ETH @ <span id="ETH_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="ETH_number_trades_buy_orders">-</span>, Sells <span id="ETH_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/ETH/octopuses">ETH octopus trades</a>
<a href="/ETH/dolphins">ETH dolphin trades</a> 💾
<a href="/ETH/whales">ETH whale trades</a> 💾

<b>Chainlink:</b>
{%- if coin == "LINK" %}
<i>Daily Volume: <span id="LINK_volume">-</span> LINK @ <span id="LINK_volume_in_currency">-</span></i>
{%- endif %}

<a href="/LINK">LINK all trades</a>
{%- if coin == "LINK" %}
<i>Daily Volume: <span id="LINK_volume">-</span> LINK @ <span id="LINK_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="LINK_number_trades_buy_orders">-</span>, Sells <span id="LINK_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/LINK/octopuses">LINK octopus trades</a>
<a href="/LINK/dolphins">LINK dolphin trades</a> 💾
<a href="/LINK/whales">LINK whale trades</a> 💾

<b>Fantom:</b>
{%- if coin == "FTM" %}
<i>Daily Volume: <span id="FTM_volume">-</span> FTM @ <span id="FTM_volume_in_currency">-</span></i>
{%- endif %}

<a href="/FTM">FTM all trades</a>
{%- if coin == "FTM" %}
<i>Daily Volume: <span id="FTM_volume">-</span> FTM @ <span id="FTM_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="FTM_number_trades_buy_orders">-</span>, Sells <span id="FTM_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/FTM/octopuses">FTM octopus trades</a>
<a href="/FTM/dolphins">FTM dolphin trades</a> 💾
<a href="/FTM/whales">FTM whale trades</a> 💾

<b>Pepe:</b>
{%- if coin == "PEPE" %}
<i>Daily Volume: <span id="PEPE_volume">-</span> PEPE @ <span id="PEPE_volume_in_currency">-</span></i>
{%- endif %}

<a href="/PEPE">PEPE all trades</a>
{%- if coin == "PEPE" %}
<i>Daily Volume: <span id="PEPE_volume">-</span> PEPE @ <span id="PEPE_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="PEPE_number_trades_buy_orders">-</span>, Sells <span id="PEPE_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/PEPE/octopuses">PEPE octopus trades</a>
<a href="/PEPE/dolphins">PEPE dolphin trades</a> 💾
<a href="/PEPE/whales">PEPE whale trades</a> 💾

<b>LTO Network:</b>
{%- if coin == "LTO" %}
<i>Daily Volume: <span id="LTO_volume">-</span> LTO @ <span id="LTO_volume_in_currency">-</span></i>
{%- endif %}

<a href="/LTO">LTO all trades</a> 💾
{%- if coin == "LTO" %}
<i>Daily Volume: <span id="LTO_volume">-</span> LTO @ <span id="LTO_volume_in_currency">-</span></i>
<i>Daily Number Trades: Buys <span id="LTO_number_trades_buy_orders">-</span>, Sells <span id="LTO_number_trades_sell_orders">-</span></i>
{%- endif %}
<a href="/LTO/octopuses">LTO octopus trades</a> 💾
<a href="/LTO/dolphins">LTO dolphin trades</a> 💾
<a href="/LTO/whales">LTO whale trades</a> 💾

0 comments on commit 79cca65

Please sign in to comment.