forked from hummingbot/hummingbot
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d0fe3e5
commit 95f9c2a
Showing
19 changed files
with
2,276 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env python | ||
|
||
from .pure_market_making import PureMarketMakingStrategy | ||
from .asset_price_delegate import AssetPriceDelegate | ||
from .order_book_asset_price_delegate import OrderBookAssetPriceDelegate | ||
from .api_asset_price_delegate import APIAssetPriceDelegate | ||
from .inventory_cost_price_delegate import InventoryCostPriceDelegate | ||
__all__ = [ | ||
PureMarketMakingStrategy, | ||
AssetPriceDelegate, | ||
OrderBookAssetPriceDelegate, | ||
APIAssetPriceDelegate, | ||
InventoryCostPriceDelegate, | ||
] |
4 changes: 4 additions & 0 deletions
4
hummingbot/strategy/pure_market_making/api_asset_price_delegate.pxd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from .asset_price_delegate cimport AssetPriceDelegate | ||
|
||
cdef class APIAssetPriceDelegate(AssetPriceDelegate): | ||
cdef object _custom_api_feed |
19 changes: 19 additions & 0 deletions
19
hummingbot/strategy/pure_market_making/api_asset_price_delegate.pyx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from .asset_price_delegate cimport AssetPriceDelegate | ||
from hummingbot.data_feed.custom_api_data_feed import CustomAPIDataFeed, NetworkStatus | ||
|
||
cdef class APIAssetPriceDelegate(AssetPriceDelegate): | ||
def __init__(self, api_url: str): | ||
super().__init__() | ||
self._custom_api_feed = CustomAPIDataFeed(api_url=api_url) | ||
self._custom_api_feed.start() | ||
|
||
cdef object c_get_mid_price(self): | ||
return self._custom_api_feed.get_price() | ||
|
||
@property | ||
def ready(self) -> bool: | ||
return self._custom_api_feed.network_status == NetworkStatus.CONNECTED | ||
|
||
@property | ||
def custom_api_feed(self) -> CustomAPIDataFeed: | ||
return self._custom_api_feed |
3 changes: 3 additions & 0 deletions
3
hummingbot/strategy/pure_market_making/asset_price_delegate.pxd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
|
||
cdef class AssetPriceDelegate: | ||
cdef object c_get_mid_price(self) |
16 changes: 16 additions & 0 deletions
16
hummingbot/strategy/pure_market_making/asset_price_delegate.pyx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from decimal import Decimal | ||
|
||
|
||
cdef class AssetPriceDelegate: | ||
# The following exposed Python functions are meant for unit tests | ||
# --------------------------------------------------------------- | ||
def get_mid_price(self) -> Decimal: | ||
return self.c_get_mid_price() | ||
# --------------------------------------------------------------- | ||
|
||
cdef object c_get_mid_price(self): | ||
raise NotImplementedError | ||
|
||
@property | ||
def ready(self) -> bool: | ||
raise NotImplementedError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#!/usr/bin/env python | ||
from typing import ( | ||
NamedTuple, | ||
List | ||
) | ||
from decimal import Decimal | ||
from hummingbot.core.event.events import OrderType | ||
|
||
ORDER_PROPOSAL_ACTION_CREATE_ORDERS = 1 | ||
ORDER_PROPOSAL_ACTION_CANCEL_ORDERS = 1 << 1 | ||
|
||
|
||
class OrdersProposal(NamedTuple): | ||
actions: int | ||
buy_order_type: OrderType | ||
buy_order_prices: List[Decimal] | ||
buy_order_sizes: List[Decimal] | ||
sell_order_type: OrderType | ||
sell_order_prices: List[Decimal] | ||
sell_order_sizes: List[Decimal] | ||
cancel_order_ids: List[str] | ||
|
||
|
||
class PricingProposal(NamedTuple): | ||
buy_order_prices: List[Decimal] | ||
sell_order_prices: List[Decimal] | ||
|
||
|
||
class SizingProposal(NamedTuple): | ||
buy_order_sizes: List[Decimal] | ||
sell_order_sizes: List[Decimal] | ||
|
||
|
||
class InventorySkewBidAskRatios(NamedTuple): | ||
bid_ratio: float | ||
ask_ratio: float | ||
|
||
|
||
class PriceSize: | ||
def __init__(self, price: Decimal, size: Decimal): | ||
self.price: Decimal = price | ||
self.size: Decimal = size | ||
|
||
def __repr__(self): | ||
return f"[ p: {self.price} s: {self.size} ]" | ||
|
||
|
||
class Proposal: | ||
def __init__(self, buys: List[PriceSize], sells: List[PriceSize]): | ||
self.buys: List[PriceSize] = buys | ||
self.sells: List[PriceSize] = sells | ||
|
||
def __repr__(self): | ||
return f"{len(self.buys)} buys: {', '.join([str(o) for o in self.buys])} " \ | ||
f"{len(self.sells)} sells: {', '.join([str(o) for o in self.sells])}" |
70 changes: 70 additions & 0 deletions
70
hummingbot/strategy/pure_market_making/inventory_cost_price_delegate.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
from decimal import Decimal, InvalidOperation | ||
from typing import Optional | ||
|
||
from hummingbot.core.event.events import OrderFilledEvent, TradeType | ||
from hummingbot.model.inventory_cost import InventoryCost | ||
from hummingbot.model.sql_connection_manager import SQLConnectionManager | ||
|
||
s_decimal_0 = Decimal("0") | ||
|
||
|
||
class InventoryCostPriceDelegate: | ||
def __init__(self, sql: SQLConnectionManager, trading_pair: str) -> None: | ||
self.base_asset, self.quote_asset = trading_pair.split("-") | ||
self._session = sql.get_shared_session() | ||
|
||
@property | ||
def ready(self) -> bool: | ||
return True | ||
|
||
def get_price(self) -> Optional[Decimal]: | ||
record = InventoryCost.get_record( | ||
self._session, self.base_asset, self.quote_asset | ||
) | ||
|
||
if record is None or record.base_volume is None or record.base_volume is None: | ||
return None | ||
|
||
try: | ||
price = record.quote_volume / record.base_volume | ||
except InvalidOperation: | ||
# decimal.InvalidOperation: [<class 'decimal.DivisionUndefined'>] - both volumes are 0 | ||
return None | ||
return Decimal(price) | ||
|
||
def process_order_fill_event(self, fill_event: OrderFilledEvent) -> None: | ||
base_asset, quote_asset = fill_event.trading_pair.split("-") | ||
quote_volume = fill_event.amount * fill_event.price | ||
base_volume = fill_event.amount | ||
|
||
for fee_asset, fee_amount in fill_event.trade_fee.flat_fees: | ||
if fill_event.trade_type == TradeType.BUY: | ||
if fee_asset == base_asset: | ||
base_volume -= fee_amount | ||
elif fee_asset == quote_asset: | ||
quote_volume += fee_amount | ||
else: | ||
# Ok, some other asset used (like BNB), assume that we paid in base asset for simplicity | ||
base_volume /= 1 + fill_event.trade_fee.percent | ||
else: | ||
if fee_asset == base_asset: | ||
base_volume += fee_amount | ||
elif fee_asset == quote_asset: | ||
# TODO: with new logic, this quote volume adjustment does not impacts anything | ||
quote_volume -= fee_amount | ||
else: | ||
# Ok, some other asset used (like BNB), assume that we paid in base asset for simplicity | ||
base_volume /= 1 + fill_event.trade_fee.percent | ||
|
||
if fill_event.trade_type == TradeType.SELL: | ||
record = InventoryCost.get_record(self._session, base_asset, quote_asset) | ||
if not record: | ||
raise RuntimeError("Sold asset without having inventory price set. This should not happen.") | ||
|
||
# We're keeping initial buy price intact. Profits are not changing inventory price intentionally. | ||
quote_volume = -(Decimal(record.quote_volume / record.base_volume) * base_volume) | ||
base_volume = -base_volume | ||
|
||
InventoryCost.add_volume( | ||
self._session, base_asset, quote_asset, base_volume, quote_volume | ||
) |
5 changes: 5 additions & 0 deletions
5
hummingbot/strategy/pure_market_making/inventory_skew_calculator.pxd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
cdef object c_calculate_bid_ask_ratios_from_base_asset_ratio(double base_asset_amount, | ||
double quote_asset_amount, | ||
double price, | ||
double target_base_asset_ratio, | ||
double base_asset_range) |
57 changes: 57 additions & 0 deletions
57
hummingbot/strategy/pure_market_making/inventory_skew_calculator.pyx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from decimal import Decimal | ||
import numpy as np | ||
|
||
from .data_types import InventorySkewBidAskRatios | ||
|
||
decimal_0 = Decimal(0) | ||
decimal_1 = Decimal(1) | ||
decimal_2 = Decimal(2) | ||
|
||
|
||
def calculate_total_order_size(order_start_size: Decimal, order_step_size: Decimal = decimal_0, | ||
order_levels: int = 1) -> Decimal: | ||
order_levels_decimal = order_levels | ||
return (decimal_2 * | ||
(order_levels_decimal * order_start_size + | ||
order_levels_decimal * (order_levels_decimal - decimal_1) / decimal_2 * order_step_size | ||
) | ||
) | ||
|
||
|
||
def calculate_bid_ask_ratios_from_base_asset_ratio( | ||
base_asset_amount: float, quote_asset_amount: float, price: float, | ||
target_base_asset_ratio: float, base_asset_range: float) -> InventorySkewBidAskRatios: | ||
return c_calculate_bid_ask_ratios_from_base_asset_ratio(base_asset_amount, | ||
quote_asset_amount, | ||
price, | ||
target_base_asset_ratio, | ||
base_asset_range) | ||
|
||
|
||
cdef object c_calculate_bid_ask_ratios_from_base_asset_ratio( | ||
double base_asset_amount, double quote_asset_amount, double price, | ||
double target_base_asset_ratio, double base_asset_range): | ||
cdef: | ||
double total_portfolio_value = base_asset_amount * price + quote_asset_amount | ||
|
||
if total_portfolio_value <= 0.0 or base_asset_range <= 0.0: | ||
return InventorySkewBidAskRatios(0.0, 0.0) | ||
|
||
cdef: | ||
double base_asset_value = base_asset_amount * price | ||
double base_asset_range_value = min(base_asset_range * price, total_portfolio_value * 0.5) | ||
double target_base_asset_value = total_portfolio_value * target_base_asset_ratio | ||
double left_base_asset_value_limit = max(target_base_asset_value - base_asset_range_value, 0.0) | ||
double right_base_asset_value_limit = target_base_asset_value + base_asset_range_value | ||
double left_inventory_ratio = np.interp(base_asset_value, | ||
[left_base_asset_value_limit, target_base_asset_value], | ||
[0.0, 0.5]) | ||
double right_inventory_ratio = np.interp(base_asset_value, | ||
[target_base_asset_value, right_base_asset_value_limit], | ||
[0.5, 1.0]) | ||
double bid_adjustment = (np.interp(left_inventory_ratio, [0, 0.5], [2.0, 1.0]) | ||
if base_asset_value < target_base_asset_value | ||
else np.interp(right_inventory_ratio, [0.5, 1], [1.0, 0.0])) | ||
double ask_adjustment = 2.0 - bid_adjustment | ||
|
||
return InventorySkewBidAskRatios(bid_adjustment, ask_adjustment) |
7 changes: 7 additions & 0 deletions
7
hummingbot/strategy/pure_market_making/order_book_asset_price_delegate.pxd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from .asset_price_delegate cimport AssetPriceDelegate | ||
from hummingbot.connector.exchange_base cimport ExchangeBase | ||
|
||
cdef class OrderBookAssetPriceDelegate(AssetPriceDelegate): | ||
cdef: | ||
ExchangeBase _market | ||
str _trading_pair |
29 changes: 29 additions & 0 deletions
29
hummingbot/strategy/pure_market_making/order_book_asset_price_delegate.pyx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from hummingbot.core.event.events import PriceType | ||
from .asset_price_delegate cimport AssetPriceDelegate | ||
from hummingbot.connector.exchange_base import ExchangeBase | ||
from decimal import Decimal | ||
|
||
cdef class OrderBookAssetPriceDelegate(AssetPriceDelegate): | ||
def __init__(self, market: ExchangeBase, trading_pair: str): | ||
super().__init__() | ||
self._market = market | ||
self._trading_pair = trading_pair | ||
|
||
cdef object c_get_mid_price(self): | ||
return (self._market.c_get_price(self._trading_pair, True) + | ||
self._market.c_get_price(self._trading_pair, False))/Decimal('2') | ||
|
||
@property | ||
def ready(self) -> bool: | ||
return self._market.ready | ||
|
||
def get_price_by_type(self, price_type: PriceType) -> Decimal: | ||
return self._market.get_price_by_type(self._trading_pair, price_type) | ||
|
||
@property | ||
def market(self) -> ExchangeBase: | ||
return self._market | ||
|
||
@property | ||
def trading_pair(self) -> str: | ||
return self._trading_pair |
78 changes: 78 additions & 0 deletions
78
hummingbot/strategy/pure_market_making/pure_market_making.pxd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# distutils: language=c++ | ||
|
||
from libc.stdint cimport int64_t | ||
from hummingbot.strategy.strategy_base cimport StrategyBase | ||
|
||
|
||
cdef class PureMarketMakingStrategy(StrategyBase): | ||
cdef: | ||
object _market_info | ||
|
||
object _bid_spread | ||
object _ask_spread | ||
object _minimum_spread | ||
object _order_amount | ||
int _order_levels | ||
int _buy_levels | ||
int _sell_levels | ||
object _order_level_spread | ||
object _order_level_amount | ||
double _order_refresh_time | ||
double _max_order_age | ||
object _order_refresh_tolerance_pct | ||
double _filled_order_delay | ||
bint _inventory_skew_enabled | ||
object _inventory_target_base_pct | ||
object _inventory_range_multiplier | ||
bint _hanging_orders_enabled | ||
object _hanging_orders_cancel_pct | ||
bint _order_optimization_enabled | ||
object _ask_order_optimization_depth | ||
object _bid_order_optimization_depth | ||
bint _add_transaction_costs_to_orders | ||
object _asset_price_delegate | ||
object _inventory_cost_price_delegate | ||
object _price_type | ||
bint _take_if_crossed | ||
object _price_ceiling | ||
object _price_floor | ||
bint _ping_pong_enabled | ||
list _ping_pong_warning_lines | ||
bint _hb_app_notification | ||
object _order_override | ||
|
||
double _cancel_timestamp | ||
double _create_timestamp | ||
object _limit_order_type | ||
bint _all_markets_ready | ||
int _filled_buys_balance | ||
int _filled_sells_balance | ||
list _hanging_order_ids | ||
double _last_timestamp | ||
double _status_report_interval | ||
int64_t _logging_options | ||
object _last_own_trade_price | ||
list _hanging_aged_order_prices | ||
|
||
cdef object c_get_mid_price(self) | ||
cdef object c_create_base_proposal(self) | ||
cdef tuple c_get_adjusted_available_balance(self, list orders) | ||
cdef c_apply_order_levels_modifiers(self, object proposal) | ||
cdef c_apply_price_band(self, object proposal) | ||
cdef c_apply_ping_pong(self, object proposal) | ||
cdef c_apply_order_price_modifiers(self, object proposal) | ||
cdef c_apply_order_size_modifiers(self, object proposal) | ||
cdef c_apply_inventory_skew(self, object proposal) | ||
cdef c_apply_budget_constraint(self, object proposal) | ||
|
||
cdef c_filter_out_takers(self, object proposal) | ||
cdef c_apply_order_optimization(self, object proposal) | ||
cdef c_apply_add_transaction_costs(self, object proposal) | ||
cdef bint c_is_within_tolerance(self, list current_prices, list proposal_prices) | ||
cdef c_cancel_active_orders(self, object proposal) | ||
cdef c_cancel_hanging_orders(self) | ||
cdef c_cancel_orders_below_min_spread(self) | ||
cdef c_aged_order_refresh(self) | ||
cdef bint c_to_create_orders(self, object proposal) | ||
cdef c_execute_orders_proposal(self, object proposal) | ||
cdef set_timers(self) |
Oops, something went wrong.