Wall Strategy¶
This strategy simply places a buy and a sell wall into a specific market using a specified account.
Example Configuration¶
# BitShares end point
node: "wss://node.bitshares.eu"
# List of Bots
bots:
# Only a single Walls Bot
Walls:
# The Walls strategy module and class
module: stakemachine.strategies.walls
bot: Walls
# The market to serve
market: HERO:BTS
# The account to sue
account: hero-market-maker
# We shall bundle operations into a single transaction
bundle: True
# Test your conditions every x blocks
test:
blocks: 10
# Where the walls should be
target:
# They relate to the price feed
reference: feed
# There should be an offset
offsets:
buy: 2.5
sell: 2.5
# We'd like to use x amount of quote (here: HERO)
# in the walls
amount:
buy: 5.0
sell: 5.0
# When the price moves by more than 2%, update the walls
threshold: 2
Source Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | from math import fabs
from pprint import pprint
from collections import Counter
from bitshares.amount import Amount
from stakemachine.basestrategy import BaseStrategy
from stakemachine.errors import InsufficientFundsError
import logging
log = logging.getLogger(__name__)
class Walls(BaseStrategy):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Define Callbacks
self.onMarketUpdate += self.test
self.ontick += self.tick
self.onAccount += self.test
self.error_ontick = self.error
self.error_onMarketUpdate = self.error
self.error_onAccount = self.error
# Counter for blocks
self.counter = Counter()
# Tests for actions
self.test_blocks = self.bot.get("test", {}).get("blocks", 0)
def error(self, *args, **kwargs):
self.disabled = True
self.cancelall()
pprint(self.execute())
def updateorders(self):
""" Update the orders
"""
log.info("Replacing orders")
# Canceling orders
self.cancelall()
# Target
target = self.bot.get("target", {})
price = self.getprice()
# prices
buy_price = price * (1 - target["offsets"]["buy"] / 100)
sell_price = price * (1 + target["offsets"]["sell"] / 100)
# Store price in storage for later use
self["feed_price"] = float(price)
# Buy Side
if float(self.balance(self.market["base"])) < buy_price * target["amount"]["buy"]:
InsufficientFundsError(Amount(target["amount"]["buy"] * float(buy_price), self.market["base"]))
self["insufficient_buy"] = True
else:
self["insufficient_buy"] = False
self.market.buy(
buy_price,
Amount(target["amount"]["buy"], self.market["quote"]),
account=self.account
)
# Sell Side
if float(self.balance(self.market["quote"])) < target["amount"]["sell"]:
InsufficientFundsError(Amount(target["amount"]["sell"], self.market["quote"]))
self["insufficient_sell"] = True
else:
self["insufficient_sell"] = False
self.market.sell(
sell_price,
Amount(target["amount"]["sell"], self.market["quote"]),
account=self.account
)
pprint(self.execute())
def getprice(self):
""" Here we obtain the price for the quote and make sure it has
a feed price
"""
target = self.bot.get("target", {})
if target.get("reference") == "feed":
assert self.market == self.market.core_quote_market(), "Wrong market for 'feed' reference!"
ticker = self.market.ticker()
price = ticker.get("quoteSettlement_price")
assert abs(price["price"]) != float("inf"), "Check price feed of asset! (%s)" % str(price)
return price
def tick(self, d):
""" ticks come in on every block
"""
if self.test_blocks:
if not (self.counter["blocks"] or 0) % self.test_blocks:
self.test()
self.counter["blocks"] += 1
def test(self, *args, **kwargs):
""" Tests if the orders need updating
"""
orders = self.orders
# Test if still 2 orders in the market (the walls)
if len(orders) < 2 and len(orders) > 0:
if (
not self["insufficient_buy"] and
not self["insufficient_sell"]
):
log.info("No 2 orders available. Updating orders!")
self.updateorders()
elif len(orders) == 0:
self.updateorders()
# Test if price feed has moved more than the threshold
if (
self["feed_price"] and
fabs(1 - float(self.getprice()) / self["feed_price"]) > self.bot["threshold"] / 100.0
):
log.info("Price feed moved by more than the threshold. Updating orders!")
self.updateorders()
|