implement losscut in MM algorithm
This commit is contained in:
parent
f6413a3389
commit
e376eea76b
66
algo/mm.py
66
algo/mm.py
@ -7,37 +7,76 @@ class MM:
|
||||
self._player = player
|
||||
self._pair = pair
|
||||
|
||||
self._lastBuy = ""
|
||||
self._lastSell = ""
|
||||
self._lastBuy = ""
|
||||
self._lastSell = ""
|
||||
self._lastPrice = None
|
||||
|
||||
self._delta = float(config["delta"])
|
||||
self._delta = float(config["delta"])
|
||||
self._positiveCut = float(config["+cut"])
|
||||
self._negativeCut = float(config["-cut"])
|
||||
|
||||
async def update(self):
|
||||
sales = self._player.assets[self._pair.names[0]]
|
||||
crncy = self._player.assets[self._pair.names[1]]
|
||||
price = self._pair.ticker.price
|
||||
|
||||
lot = (sales.amount + crncy.amount / price) / 2
|
||||
pos = sales.amount / lot - 1
|
||||
|
||||
# evaluate if cutting should be executed
|
||||
negCut = False
|
||||
posCut = False
|
||||
if self._lastPrice is not None:
|
||||
change = (price - self._lastPrice) / self._lastPrice
|
||||
negCut = pos > 0.5 and change < -abs(self._negativeCut)
|
||||
posCut = pos < -0.5 and change > abs(self._positiveCut)
|
||||
cutting = negCut or posCut
|
||||
|
||||
# check if the past orders are active
|
||||
lastBuyAgreed = (self._lastBuy is not None and
|
||||
self._lastBuy not in self._player.orders)
|
||||
lastSellAgreed = (self._lastSell is not None and
|
||||
self._lastSell not in self._player.orders)
|
||||
|
||||
if not lastBuyAgreed and not lastSellAgreed:
|
||||
if not lastBuyAgreed and not lastSellAgreed and not cutting:
|
||||
return
|
||||
|
||||
# cancel active orders
|
||||
cancel_orders = []
|
||||
if not lastBuyAgreed and self._lastBuy is not None:
|
||||
logging.info(f"cancel buy")
|
||||
cancel_orders.append(self._lastBuy)
|
||||
self._lastBuy = None
|
||||
elif lastBuyAgreed:
|
||||
logging.info(f"agree buy")
|
||||
|
||||
if not lastSellAgreed and self._lastSell is not None:
|
||||
logging.info(f"cancel sell")
|
||||
cancel_orders.append(self._lastSell)
|
||||
self._lastSell = None
|
||||
elif lastSellAgreed:
|
||||
logging.info(f"agree sell")
|
||||
|
||||
if len(cancel_orders) != 0:
|
||||
await self._player.cancel(self._pair.names, cancel_orders)
|
||||
|
||||
sales = self._player.assets[self._pair.names[0]]
|
||||
crncy = self._player.assets[self._pair.names[1]]
|
||||
price = self._pair.ticker.price
|
||||
|
||||
lot = (sales.amount + crncy.amount / price) / 4
|
||||
pos = sales.amount / lot - 2
|
||||
# execute cutting
|
||||
if cutting:
|
||||
if negCut:
|
||||
logging.info(f"-cut (change: {change}, pos: {pos} -> 0)")
|
||||
if posCut:
|
||||
logging.info(f"+cut (change: {change}, pos: {pos} -> 0)")
|
||||
self._lastPrice = None
|
||||
self._lastBuy = None
|
||||
self._lastSell = None
|
||||
sell_amount = pos * lot
|
||||
if sell_amount > 0:
|
||||
await self._player.orderMarketSell(self._pair.names, amount=sell_amount)
|
||||
else:
|
||||
await self._player.orderMarketBuy(self._pair.names, amount=-buy_amount)
|
||||
return
|
||||
|
||||
# execute new cycle
|
||||
buy_amount = _quad( pos) * lot
|
||||
sell_amount = _quad(-pos) * lot
|
||||
|
||||
@ -46,6 +85,8 @@ class MM:
|
||||
|
||||
order_unit = pow(10, -sales.precision)
|
||||
|
||||
logging.info(f"new cycle (pos: {pos}, price: {price}, buy: {buy_amount}, sell: {sell_amount})")
|
||||
|
||||
async def buy():
|
||||
return (None if order_unit > buy_amount else
|
||||
await self._player.orderLimitBuy(
|
||||
@ -57,8 +98,9 @@ class MM:
|
||||
self._pair.names, amount = sell_amount, price = sell_price))
|
||||
|
||||
orders = await asyncio.gather(buy(), sell())
|
||||
self._lastBuy = orders[0]
|
||||
self._lastSell = orders[1]
|
||||
self._lastBuy = orders[0]
|
||||
self._lastSell = orders[1]
|
||||
self._lastPrice = price
|
||||
|
||||
# https://kijitora-2018.hatenablog.com/entry/2018/12/23/102913
|
||||
def _quad(x):
|
||||
|
2
main.py
2
main.py
@ -14,6 +14,8 @@ with open("config.json", "r") as file:
|
||||
config = json.load(file)
|
||||
|
||||
async def main():
|
||||
logging.info("#### TMM ####")
|
||||
|
||||
alive = True
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
|
@ -14,6 +14,24 @@ class Player:
|
||||
})
|
||||
self._check(res)
|
||||
|
||||
async def orderMarketSell(self, pair, amount):
|
||||
res = await self._post("user/spot/order", data={
|
||||
"pair": f"{pair[0]}_{pair[1]}",
|
||||
"amount": str(amount),
|
||||
"side": "sell",
|
||||
"type": "market",
|
||||
})
|
||||
return self._check(res)["data"]["order_id"]
|
||||
|
||||
async def orderMarketBuy(self, pair, amount):
|
||||
res = await self._post("user/spot/order", data={
|
||||
"pair": f"{pair[0]}_{pair[1]}",
|
||||
"amount": str(amount),
|
||||
"side": "buy",
|
||||
"type": "market",
|
||||
})
|
||||
return self._check(res)["data"]["order_id"]
|
||||
|
||||
async def orderLimitSell(self, pair, amount, price):
|
||||
res = await self._post("user/spot/order", data={
|
||||
"pair": f"{pair[0]}_{pair[1]}",
|
||||
|
Loading…
Reference in New Issue
Block a user