Skip to content

Commit

Permalink
restructure max_investment estimation
Browse files Browse the repository at this point in the history
  • Loading branch information
btschwertfeger committed Jan 8, 2025
1 parent 38c7e85 commit 4b8e140
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 78 deletions.
27 changes: 22 additions & 5 deletions src/kraken_infinity_grid/gridbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ def __init__(
self.amount_per_grid: float = float(config["amount_per_grid"])
self.max_investment: float = config["max_investment"]
self.n_open_buy_orders: int = config["n_open_buy_orders"]
self.max_invest_reached: bool = False
self.investment: float = 0
self.fee: float | None = None
self.base_currency: str = config["base_currency"]
self.quote_currency: str = config["quote_currency"]
Expand Down Expand Up @@ -558,8 +556,27 @@ def get_order_price(
def get_value_of_orders(self: Self, orders: Iterable) -> float:
"""Returns the overall invested quote that is invested"""
LOG.debug("Getting value of open orders...")
investment = 0.0
for order in orders:
investment += float(order["price"]) * float(order["volume"])
investment = sum(
float(order["price"]) * float(order["volume"]) for order in orders
)
LOG.debug("Value of open orders: %d %s", investment, self.quote_currency)
return investment

@property
def investment(self: Self) -> float:
"""Returns the current investment based on open orders."""
return self.__s.get_value_of_orders( # type: ignore[no-any-return]
orders=self.__s.orderbook.get_orders(),
)

@property
def max_investment_reached(self: Self) -> bool:
"""Returns True if the maximum investment is reached."""
# TODO: put this as class variable
new_position_value = (
self.__s.amount_per_grid + self.__s.amount_per_grid * self.__s.fee
)

return (self.max_investment <= self.investment + new_position_value) or (
self.max_investment <= self.investment
)
103 changes: 37 additions & 66 deletions src/kraken_infinity_grid/order_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ def assign_order_by_txid(self: Self, txid: str, tries: int = 1) -> None:
self.__s.orderbook.update(order_to_assign, filters={"txid": txid})
LOG.info("%s: Updated order in orderbook.", txid)

self.__s.investment = self.__s.get_value_of_orders(
orders=self.__s.orderbook.get_orders().all(), # type: ignore[no-untyped-call]
)
LOG.info(
"Current invested value: %f / %d %s",
self.__s.investment,
Expand Down Expand Up @@ -159,7 +156,6 @@ def __check_n_open_buy_orders(self: OrderManager) -> None:
len(active_buy_orders) < self.__s.n_open_buy_orders
and can_place_buy_order
and self.__s.pending_txids.count() == 0
and self.__s.max_investment > self.__s.investment
and not self.__s.max_invest_reached
):

Expand Down Expand Up @@ -344,6 +340,13 @@ def new_buy_order(
# FIXME: do proper dryrun
return

if txid_to_delete is not None:
self.__s.orderbook.remove(filters={"txid": txid_to_delete})

# Check if algorithm reached the max_investment value
if self.__s.max_invest_reached:
return

current_balances = self.__s.get_balances()

# Compute the target price for the upcoming buy order.
Expand All @@ -369,76 +372,44 @@ def new_buy_order(
self.__s.amount_per_grid + self.__s.amount_per_grid * self.__s.fee
)

# Compute the value of all open orders.
value_of_open_orders = self.__s.get_value_of_orders(
orders=self.__s.orderbook.get_orders(exclude={"txid": txid_to_delete}),
)

# ======================================================================
# Check if there is enough quote balance available to place a buy order.
if current_balances["quote_available"] > new_position_value:
# Check if algorithm reached the max_investment value
if self.__s.max_investment <= value_of_open_orders + new_position_value:
if not self.__s.max_invest_reached:
# Ensuring the message below is only sent once
self.__s.max_invest_reached = True

if txid_to_delete is not None:
self.__s.orderbook.remove(filters={"txid": txid_to_delete})

message = str(
"Bot reached maximum value, not buying. (max value:"
f" {self.__s.max_investment} {self.__s.quote_currency},"
" current invested value:"
f"{round(value_of_open_orders, self.__s.cost_decimals)}"
f" {self.__s.quote_currency})",
)
self.__s.t.send_to_telegram(message=message)
return

# ==============================================================
# Algorithm has not reached max_investment yet and is ready to buy.
else:
self.__s.max_invest_reached = False
LOG.info(
"Placing order to buy %s %s @ %s %s.",
volume,
self.__s.base_currency,
order_price,
self.__s.quote_currency,
)
LOG.info(
"Placing order to buy %s %s @ %s %s.",
volume,
self.__s.base_currency,
order_price,
self.__s.quote_currency,
)

# Place a new buy order, append txid to pending list and delete
# corresponding sell order from local orderbook.
placed_order = self.__s.trade.create_order(
ordertype="limit",
side="buy",
volume=volume,
pair=self.__s.symbol,
price=order_price,
userref=self.__s.userref,
validate=self.__s.dry_run,
)
# Place a new buy order, append txid to pending list and delete
# corresponding sell order from local orderbook.
placed_order = self.__s.trade.create_order(
ordertype="limit",
side="buy",
volume=volume,
pair=self.__s.symbol,
price=order_price,
userref=self.__s.userref,
validate=self.__s.dry_run,
)

self.__s.pending_txids.add(placed_order["txid"][0])
if txid_to_delete is not None:
self.__s.orderbook.remove(filters={"txid": txid_to_delete})
self.__s.om.assign_order_by_txid(placed_order["txid"][0])
return
self.__s.pending_txids.add(placed_order["txid"][0])
# if txid_to_delete is not None:
# self.__s.orderbook.remove(filters={"txid": txid_to_delete})
self.__s.om.assign_order_by_txid(placed_order["txid"][0])
return

# ======================================================================
# Not enough available funds to place a buy order.
else:
if txid_to_delete is not None:
self.__s.orderbook.remove(filters={"txid": txid_to_delete})

message = f"⚠️ {self.__s.symbol}"
message += f"├ Not enough {self.__s.quote_currency}"
message += f"├ to buy {volume} {self.__s.base_currency}"
message += f"└ for {order_price} {self.__s.quote_currency}"
self.__s.t.send_to_telegram(message)
LOG.warning("Current balances: %s", current_balances)
return
message = f"⚠️ {self.__s.symbol}"
message += f"├ Not enough {self.__s.quote_currency}"
message += f"├ to buy {volume} {self.__s.base_currency}"
message += f"└ for {order_price} {self.__s.quote_currency}"
self.__s.t.send_to_telegram(message)
LOG.warning("Current balances: %s", current_balances)
return

def new_sell_order( # noqa: C901
self: OrderManager,
Expand Down
7 changes: 0 additions & 7 deletions src/kraken_infinity_grid/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,6 @@ def prepare_for_trading(self: Self) -> None:

self.__s.ticker = SimpleNamespace(last=float(ticker["c"][0]))

# Check how much is actual invested in this asset pair based on the open
# orders of this instance.
##
self.__s.investment = self.__s.get_value_of_orders(
orders=self.__s.orderbook.get_orders(),
)

# Update the orderbook, check for closed, filled, cancelled trades,
# and submit new orders if necessary.
##
Expand Down

0 comments on commit 4b8e140

Please sign in to comment.