Skip to content

Commit

Permalink
[MAINNET] Test BB strategy #24
Browse files Browse the repository at this point in the history
  • Loading branch information
4TT1L4 committed Apr 17, 2024
1 parent deb63b6 commit 25f7213
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 30 deletions.
7 changes: 6 additions & 1 deletion api.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def get_own_orders(self, market_id : str):
return cast(OrderBookInfo, self.process_response(response))

def get_price_history(self, market_id : str, resolution : str, from_date : str | Unset = UNSET, until_date: Unset | str = UNSET, sort="asc", limit=1000):
response: Response[ErrorResponse | List[MarketOHLC]] = get_historical_prices_maestro_market_dex.sync_detailed(client=self.client, market=market_id, dex="genius-yield", resolution=resolution, from_=from_date, to=until_date)
response: Response[ErrorResponse | List[MarketOHLC]] = get_historical_prices_maestro_market_dex.sync_detailed(client=self.client, market=market_id, dex="genius-yield", resolution=resolution, from_=from_date, to=until_date, sort=sort, limit=limit)
return cast(List[MarketOHLC], self.process_response(response))

def get_market_price(self, market_id : str):
Expand All @@ -70,6 +70,10 @@ def get_market_price(self, market_id : str):

def place_order(self, offered_amount : str, offered_token : str, price_token : str, price_amount : str):
self.logger.info(f"[PLACE-ORDER] Placing order...")
self.logger.info(f"[PLACE-ORDER] offered_amount: {offered_amount}")
self.logger.info(f"[PLACE-ORDER] offered_token: {offered_token}")
self.logger.info(f"[PLACE-ORDER] price_token: {price_token}")
self.logger.info(f"[PLACE-ORDER] price_amount: {price_amount}")
body = PostOrderParameters()
body.offer_amount = offered_amount
body.offer_token = offered_token
Expand All @@ -83,6 +87,7 @@ def place_order(self, offered_amount : str, offered_token : str, price_token : s

def cancel_order(self, order_reference : str):
self.logger.info(f"[CANCEL-ORDER] Canceling order...")
self.logger.info(f"[CANCEL-ORDER] order_reference: {order_reference}")
body = DeleteOrderParameters()
body.address=self.own_address
body.order_references=[order_reference]
Expand Down
4 changes: 2 additions & 2 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ def worker():
try:
strategy.execute(api_client, CONFIG, logger)
except Exception:
logger.error(f" ❌ Strategy exeuction has failed with an exception. ❌ ")
logger.error(f" ❌ Strategy execution has failed with an exception. ❌ ")
logger.exception(" ❌ Exception occurred:")
else:
logger.info(f"[OK] Strategy exeuction has been finished ✅ ")
logger.info(f"[OK] Strategy execution has been finished ✅ ")
finally:
end_time = time.time()
execution_time = end_time - start_time
Expand Down
9 changes: 6 additions & 3 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
coreProvider:
maestroToken: <<CORE_MAESTRO_API_KEY>>
turboSubmit: false
networkId: "preprod" # supported: mainnet ot preprod
networkId: "mainnet" # supported: mainnet ot preprod
logging:
- type: {tag: stderr}
severity: "Debug" # Options: Debug, Info, Warning or Error
Expand Down Expand Up @@ -72,8 +72,11 @@ services:
STRATEGY: bollinger_bands_strategy
CONFIG: |
BASE_ASSET: lovelace
TARGET_ASSET: c6e65ba7878b2f8ea0ad39287d3e2fd256dc5c4160fc19bdf4c4d87e.7447454e53
POSITION_SIZE_LOVELACES: 10000000
# GENS for MAINNET:
TARGET_ASSET: dda5fdb1002f7389b33e036b6afee82a8189becb6cba852e8b79b4fb.0014df1047454e53
# tGENS for PRERPOD:
# TARGET_ASSET: c6e65ba7878b2f8ea0ad39287d3e2fd256dc5c4160fc19bdf4c4d87e.7447454e53
POSITION_SIZE_LOVELACES: 1000000
STD_DEV_MULTIPLIER: 1.5
PERIOD: 5
depends_on:
Expand Down
50 changes: 26 additions & 24 deletions strategies/bollinger_bands_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self, api_client, CONFIG, logger):
# Create the BB strategy instance with the config:
self.bb = BB(self.period, self.std_dev_multiplier)

def place_buy_order(self, api_client, logger):
def place_buy_order(self, api_client, logger, price):
logger.info(" ⚙️ Placing BUY order...")

if not self.buy_order_ref == None:
Expand All @@ -70,34 +70,31 @@ def place_buy_order(self, api_client, logger):
logger.exception(f" > ⚠️ [FAILED] could not cancel order: {self.sell_order_ref} ⚠️")
logger.error(f" > Exception! ")
try:
HUNDRED_ADA=100000000
balance_available = int(api_client.get_balances().get(self.base_asset, 0)) - HUNDRED_ADA
balance_available = int(api_client.get_balances().get(self.base_asset, 0))
logger.debug(f" > balance_available : {balance_available}")
logger.debug(f" > self.position_size: {self.position_size}")

# Get best ask price:
order_book = api_client.get_order_book(self.market)
best_ask_price = float(order_book.asks[-1].price)
order_size = min(self.position_size, balance_available) / float(best_ask_price)
order_size = min(self.position_size, balance_available)
if not order_size:
logger.info(" ⚠️ Insufficient balance to place BUY order! ⚠️")
return

logger.info(f" > Place BUY order: {order_size}...")
offered_amount = int(math.floor(order_size))

logger.info(f" > Place BUY order: {offered_amount} at price {price}...")
response = api_client.place_order(
offered_amount=f"{offered_amount}",
offered_token=self.base_asset,
price_token=self.target_asset,
price_amount=f"{int(math.floor(offered_amount * best_ask_price))}"
price_amount=f"{int(math.floor(offered_amount / price))}"
)
logger.info(f" > [OK] PLACED NEW BUY ORDER: {response.order_ref}")
self.buy_order_ref=response.order_ref
except:
logger.error(" > ⚠️ [FAILED] Could not place BUY order. ⚠️")
logger.exception(f" > Exception! ")

def place_sell_order(self, api_client, logger):
def place_sell_order(self, api_client, logger, price):
logger.info("Placing SELL order...")

if not self.sell_order_ref == None:
Expand All @@ -116,22 +113,21 @@ def place_sell_order(self, api_client, logger):
logger.error(f" > ⚠️ [FAILED] could not cancel order: {self.buy_order_ref} ⚠️")
logger.exception(f" > Exception! ")
try:
balance_available = api_client.get_balances().get(self.target_asset, 0)
balance_available = int(api_client.get_balances().get(self.target_asset, 0))
logger.info(f" > balance_available : {balance_available}")

order_book = api_client.get_order_book(self.market)
best_bid_price = order_book.bids[-1].price
order_size = min(self.position_size, balance_available) / float(best_bid_price)
order_size = min(self.position_size / price, balance_available)
logger.info(f" > order_size : {order_size}")
logger.info(f" > price : {price}")
if not order_size:
logger.info("⚠️ Insufficient balance to place SELL order! ⚠️")
return

logger.info(f" > Place SELL order: {order_size} at ...")
logger.info(f" > Place SELL order: {order_size} at price {price}...")
response = api_client.place_order(
offered_amount=f"{int(math.floor(order_size))}",
offered_token=self.target_asset,
price_token=self.target_asset,
price_amount=f"{int(math.floor(best_bid_price))}"
price_token=self.base_asset,
price_amount=f"{int(math.floor(order_size * price))}"
)
logger.info(f" > [OK] PLACED NEW SELL ORDER: {response.order_ref}")
self.sell_order_ref=response.order_ref
Expand All @@ -144,7 +140,7 @@ def process_candle(self, candle):
self.logger.info(f" > processsing candle - timestamp: {candle.timestamp} - base_close: {candle.base_close}")

if (not self.last_candle == None) and (self.last_candle.timestamp == candle.timestamp):
self.logger.info(f" > Candle has already been processsed.")
self.logger.info(f" > Candle has already been processsed. Nothing to do.")
return

self.last_candle = candle
Expand All @@ -171,14 +167,18 @@ def process_candle(self, candle):
self.logger.info(f" > Upper band: {self.bb[-1].ub}")
self.logger.info(f" > Lower band: {self.bb[-1].lb}")

if self.initialized == False:
self.logger.info(f" -> Initializaion phase. Do not place orders yet.")
return

# Price moved below lower band ?
if self._values[-2] >= self.bb[-2].lb and self._values[-1] < self.bb[-1].lb:
self.logger.info(f" > Price moved below the lower band -> BUY! 🛒 🛒 🛒 ")
self.place_buy_order(self.api_client, self.logger)
self.logger.info(f" -> Price moved below the lower band -> BUY! 🛒 🛒 🛒 ")
self.place_buy_order(self.api_client, self.logger, candle.base_close)
# Price moved above upper band ?
elif self._values[-2] <= self.bb[-2].ub and self._values[-1] > self.bb[-1].ub:
self.logger.info(f" > Price moved above the upper band -> SELL! 💲 💲 💲 ")
self.place_sell_order(self.api_client, self.logger)
self.logger.info(f" -> Price moved above the upper band -> SELL! 💲 💲 💲 ")
self.place_sell_order(self.api_client, self.logger, candle.base_close)

self.logger.info(f" Orders: ")
self.logger.info(f" > On-Chain BUY order: {self.buy_order_ref} ")
Expand All @@ -190,10 +190,12 @@ def execute(self, api_client : Api, CONFIG, logger):

if self.last_execution_time is None:
logger.info("Executing for the first time")
candles = api_client.get_price_history(self.market, resolution="1m", sort="asc", limit=self.period)
candles = api_client.get_price_history(self.market, resolution="1m", sort="asc", limit=self.period*5)
for candle in candles[:-1]:
self.process_candle(candle)
time.sleep(1)
self.initialized = True
self.last_candle=None
else:
time_since_last_execution = (current_time - self.last_execution_time).total_seconds()
logger.info(f"Last executed: {self.last_execution_time}")
Expand Down

0 comments on commit 25f7213

Please sign in to comment.