diff --git a/autostart_hummingbot_compose/hummingbot_files/scripts/simple_pmm_example.py b/autostart_hummingbot_compose/hummingbot_files/scripts/simple_pmm_example.py new file mode 100644 index 0000000..5a7eb91 --- /dev/null +++ b/autostart_hummingbot_compose/hummingbot_files/scripts/simple_pmm_example.py @@ -0,0 +1,77 @@ +import logging +from decimal import Decimal +from typing import List + +from hummingbot.core.data_type.common import OrderType, PriceType, TradeType +from hummingbot.core.data_type.order_candidate import OrderCandidate +from hummingbot.core.event.events import OrderFilledEvent +from hummingbot.strategy.script_strategy_base import ScriptStrategyBase + + +class SimplePMM(ScriptStrategyBase): + """ + BotCamp Cohort: Sept 2022 + Design Template: https://hummingbot-foundation.notion.site/Simple-PMM-63cc765486dd42228d3da0b32537fc92 + Video: - + Description: + The bot will place two orders around the price_source (mid price or last traded price) in a trading_pair on + exchange, with a distance defined by the ask_spread and bid_spread. Every order_refresh_time in seconds, + the bot will cancel and replace the orders. + """ + bid_spread = 0.001 + ask_spread = 0.001 + order_refresh_time = 15 + order_amount = 0.1 + create_timestamp = 0 + trading_pair = "ETH-USDT" + exchange = "binance_paper_trade" + # Here you can use for example the LastTrade price to use in your strategy + price_source = PriceType.MidPrice + + markets = {exchange: {trading_pair}} + + def on_tick(self): + if self.create_timestamp <= self.current_timestamp: + self.cancel_all_orders() + proposal: List[OrderCandidate] = self.create_proposal() + proposal_adjusted: List[OrderCandidate] = self.adjust_proposal_to_budget(proposal) + self.place_orders(proposal_adjusted) + self.create_timestamp = self.order_refresh_time + self.current_timestamp + + def create_proposal(self) -> List[OrderCandidate]: + ref_price = self.connectors[self.exchange].get_price_by_type(self.trading_pair, self.price_source) + buy_price = ref_price * Decimal(1 - self.bid_spread) + sell_price = ref_price * Decimal(1 + self.ask_spread) + + buy_order = OrderCandidate(trading_pair=self.trading_pair, is_maker=True, order_type=OrderType.LIMIT, + order_side=TradeType.BUY, amount=Decimal(self.order_amount), price=buy_price) + + sell_order = OrderCandidate(trading_pair=self.trading_pair, is_maker=True, order_type=OrderType.LIMIT, + order_side=TradeType.SELL, amount=Decimal(self.order_amount), price=sell_price) + + return [buy_order, sell_order] + + def adjust_proposal_to_budget(self, proposal: List[OrderCandidate]) -> List[OrderCandidate]: + proposal_adjusted = self.connectors[self.exchange].budget_checker.adjust_candidates(proposal, all_or_none=True) + return proposal_adjusted + + def place_orders(self, proposal: List[OrderCandidate]) -> None: + for order in proposal: + self.place_order(connector_name=self.exchange, order=order) + + def place_order(self, connector_name: str, order: OrderCandidate): + if order.order_side == TradeType.SELL: + self.sell(connector_name=connector_name, trading_pair=order.trading_pair, amount=order.amount, + order_type=order.order_type, price=order.price) + elif order.order_side == TradeType.BUY: + self.buy(connector_name=connector_name, trading_pair=order.trading_pair, amount=order.amount, + order_type=order.order_type, price=order.price) + + def cancel_all_orders(self): + for order in self.get_active_orders(connector_name=self.exchange): + self.cancel(self.exchange, order.trading_pair, order.client_order_id) + + def did_fill_order(self, event: OrderFilledEvent): + msg = (f"{event.trade_type.name} {round(event.amount, 2)} {event.trading_pair} {self.exchange} at {round(event.price, 2)}") + self.log_with_clock(logging.INFO, msg) + self.notify_hb_app_with_timestamp(msg) \ No newline at end of file