Skip to content

Commit

Permalink
Fix broken critical parts of APIs reported by mypy (#631)
Browse files Browse the repository at this point in the history
* Fix broken critical parts of APIs reported by mypy

* Update peer dependencies

* Add missing table
  • Loading branch information
carkod authored Dec 2, 2024
1 parent de7c205 commit 3f52a71
Show file tree
Hide file tree
Showing 32 changed files with 868 additions and 653 deletions.
6 changes: 2 additions & 4 deletions api/account/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,10 @@ def get_raw_balance(self, asset=None) -> list:
return balances[0]
return balances

def get_margin_balance(self, symbol="BTC"):
def get_margin_balance(self, symbol="BTC") -> float:
# Response after request
data = self.get_isolated_balance(symbol)
symbol_balance = next(
(x["free"] for x in data["data"] if x["asset"] == symbol), None
)
symbol_balance = next((x["free"] for x in data if x["asset"] == symbol), 0)
return symbol_balance

def matching_engine(self, symbol: str, order_side: bool, qty=None):
Expand Down
1 change: 1 addition & 0 deletions api/alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# mypy: ignore-errors
import logging
import os
from dotenv import load_dotenv
Expand Down
12 changes: 6 additions & 6 deletions api/apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def get_server_time(self):
data = self.request(url=self.server_time_url)
return data["serverTime"]

def signed_request(self, url, method="GET", payload: dict = {}):
def signed_request(self, url, method="GET", payload: dict = {}) -> dict:
"""
USER_DATA, TRADE signed requests
Expand Down Expand Up @@ -129,8 +129,8 @@ def get_listen_key(self):
headers = {"Content-Type": "application/json", "X-MBX-APIKEY": self.key}
res = request(method="POST", url=self.user_data_stream, headers=headers)
response = handle_binance_errors(res)
data: str = response["listenKey"]
return data
listen_key = response["listenKey"]
return listen_key

"""
No security endpoints
Expand Down Expand Up @@ -240,7 +240,7 @@ def transfer_isolated_margin_to_spot(self, asset, symbol, amount):
},
)

def transfer_spot_to_isolated_margin(self, asset: str, symbol: str, amount: str):
def transfer_spot_to_isolated_margin(self, asset: str, symbol: str, amount: float):
return self.signed_request(
self.margin_isolated_transfer_url,
method="POST",
Expand All @@ -249,7 +249,7 @@ def transfer_spot_to_isolated_margin(self, asset: str, symbol: str, amount: str)
"transTo": "ISOLATED_MARGIN",
"asset": asset,
"symbol": symbol,
"amount": amount,
"amount": str(amount),
},
)

Expand Down Expand Up @@ -289,7 +289,7 @@ def get_margin_repay_details(self, asset: str, isolatedSymbol: str):
)

def repay_margin_loan(
self, asset: str, symbol: str, amount: float, isIsolated: str
self, asset: str, symbol: str, amount: float | int, isIsolated: str
):
return self.signed_request(
self.margin_repay_url,
Expand Down
46 changes: 34 additions & 12 deletions api/autotrade/controller.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from sqlmodel import Session, select
from database.utils import independent_session
from database.models.autotrade_table import AutotradeTable, TestAutotradeTable
from autotrade.schemas import AutotradeSettingsSchema
import typing

from base_producer import AsyncBaseProducer
from database.models.autotrade_table import AutotradeTable, TestAutotradeTable
from database.utils import independent_session
from sqlmodel import Session, select
from tools.enum_definitions import AutotradeSettingsDocument


Expand All @@ -21,23 +22,43 @@ def __init__(
self.document_id = document_id
if session is None:
session = independent_session()

self.session = session
if document_id == AutotradeSettingsDocument.settings:
self.table = AutotradeTable
if document_id == AutotradeSettingsDocument.test_autotrade_settings:
self.table = TestAutotradeTable

@typing.no_type_check
def get_settings(self):
statement = select(self.table).where(self.table.id == self.document_id)
"""
Mypy check ignored: Incompatible types in assignment
should not affect execution of statement.
This is to avoid dup code
"""
if self.document_id == AutotradeSettingsDocument.test_autotrade_settings:
statement = select(TestAutotradeTable).where(
TestAutotradeTable.id == self.document_id
)
else:
statement = select(AutotradeTable).where(
AutotradeTable.id == self.document_id
)

results = self.session.exec(statement)
# Should always return one result
settings = results.first()
self.session.close()
return settings

@typing.no_type_check
def edit_settings(self, data):
settings_data = AutotradeSettingsSchema.model_validate(data)
settings = self.session.get(self.table, settings_data.id)
"""
Mypy check ignored: Incompatible types in assignment
should not affect execution of statement.
This is to avoid dup code
"""
if self.document_id == AutotradeSettingsDocument.test_autotrade_settings:
settings_data = TestAutotradeTable.model_validate(data)
settings = self.session.get(TestAutotradeTable, settings_data.id)
else:
settings_data = AutotradeTable.model_validate(data)
settings = self.session.get(AutotradeTable, settings_data.id)

if not settings:
return settings
Expand All @@ -51,4 +72,5 @@ def edit_settings(self, data):
# end of db operations
# update the producer to reload streaming data
AsyncBaseProducer().update_required("UPDATE_AUTOTRADE_SETTINGS")
self.session.close()
return settings
11 changes: 8 additions & 3 deletions api/autotrade/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Annotated

from sqlmodel import Session
from tools.enum_definitions import AutotradeSettingsDocument
from database.utils import get_session
from autotrade.controller import AutotradeSettingsController
from autotrade.schemas import AutotradeSettingsResponse, AutotradeSettingsSchema
Expand All @@ -21,7 +22,9 @@ def edit_settings(
these use real money and real Binance transactions
"""
try:
AutotradeSettingsController(session=session).edit_settings(item)
result = AutotradeSettingsController(session=session).edit_settings(item)
if not result:
raise HTTPException(status_code=404, detail="Autotrade settings not found")
return json_response({"message": "Successfully updated settings"})
except ValidationError as error:
msg = ""
Expand Down Expand Up @@ -55,7 +58,8 @@ def get_test_autotrade_settings(
):
try:
deserialized_data = AutotradeSettingsController(
document_id="test_autotrade_settings", session=session
document_id=AutotradeSettingsDocument.test_autotrade_settings,
session=session,
).get_settings()
return json_response(
{
Expand All @@ -74,7 +78,8 @@ def edit_test_autotrade_settings(
):
try:
data = AutotradeSettingsController(
document_id="test_autotrade_settings", session=session
document_id=AutotradeSettingsDocument.test_autotrade_settings,
session=session,
).edit_settings(item)
if not data:
raise HTTPException(status_code=404, detail="Autotrade settings not found")
Expand Down
20 changes: 20 additions & 0 deletions api/autotrade/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,23 @@ class AutotradeSettingsSchema(BaseModel):

class AutotradeSettingsResponse(StandardResponse):
data: AutotradeSettingsSchema


class TestAutotradeSettingsSchema(BaseModel):
id: AutotradeSettingsDocument = AutotradeSettingsDocument.settings
autotrade: bool = False
updated_at: float = time() * 1000
# Assuming 10 USDC is the minimum, adding a bit more to avoid MIN_NOTIONAL fail
base_order_size: float = 15
candlestick_interval: BinanceKlineIntervals = BinanceKlineIntervals.fifteen_minutes
trailling: bool = False
trailling_deviation: float = 3
trailling_profit: float = 2.4
stop_loss: float = 0
take_profit: float = 2.3
balance_to_use: str = "USDC"
balance_size_to_use: float = 100
max_request: int = 950
# Number of times update is requested
telegram_signals: bool = True
max_active_autotrade_bots: int = 1
14 changes: 4 additions & 10 deletions api/bots/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from fastapi.exceptions import RequestValidationError
from account.account import Account
from database.db import Database
from deals.schema import MarginOrderSchema
from deals.models import BinanceOrderModel, DealModel
from base_producer import BaseProducer
from tools.enum_definitions import BinbotEnums, DealType, Status, Strategy
Expand All @@ -18,22 +17,18 @@


class Bot(Database, Account):
def __init__(self, collection_name="paper_trading"):
def __init__(self, collection_name="bots"):
super().__init__()
self.db_collection = self._db[collection_name]
self.base_producer = BaseProducer()
self.producer = self.base_producer.start_producer()
self.deal: CreateDealController | None = None

def set_deal_controller(self, bot: BotSchema, collection="bots"):
self.deal = CreateDealController(bot, db_collection=collection)
pass

def get_active_pairs(self, symbol: str | None = None):
"""
Get distinct (non-repeating) bots by status active
"""
params = {"status": Status.active}
params = {"status": Status.active.value}
if symbol:
params["pair"] = symbol

Expand Down Expand Up @@ -234,7 +229,7 @@ def deactivate(self, bot: BotSchema) -> dict:

if bot.strategy == Strategy.margin_short:
order_res = deal_controller.margin_liquidation(bot.pair)
panic_close_order = MarginOrderSchema(
panic_close_order = BinanceOrderModel(
timestamp=order_res["transactTime"],
deal_type=DealType.panic_close,
order_id=order_res["orderId"],
Expand All @@ -245,7 +240,6 @@ def deactivate(self, bot: BotSchema) -> dict:
qty=order_res["origQty"],
time_in_force=order_res["timeInForce"],
status=order_res["status"],
is_isolated=order_res["isIsolated"],
)

bot.total_commission = self.calculate_total_commissions(order_res["fills"])
Expand All @@ -258,7 +252,7 @@ def deactivate(self, bot: BotSchema) -> dict:
self.update_deal_logs(error.message, bot)
bot.status = Status.completed
bot = self.save_bot_streaming(bot)
return bot
return bot.model_dump()

panic_close_order = BinanceOrderModel(
timestamp=res["transactTime"],
Expand Down
Loading

0 comments on commit 3f52a71

Please sign in to comment.