adding some basic exchange

This commit is contained in:
2023-01-22 14:46:05 +01:00
parent 841b49caec
commit 3a421ceb34
5 changed files with 188 additions and 1 deletions
Binary file not shown.
+2 -1
View File
@@ -1,5 +1,5 @@
class Business():
def __init__(self,production,balance) -> None:
def __init__(self,id,production,balance) -> None:
"""production (dict): {
name: 'Gem',
amount: 4,
@@ -10,6 +10,7 @@ class Business():
}
balance (int): Starting Balance
"""
self.id=id
self.production=production
self.balance=balance
#Setup Inventory
+172
View File
@@ -0,0 +1,172 @@
_bal="balance"
from lightmatchingengine.lightmatchingengine import LightMatchingEngine,Side,Trade,Order
class Exchange():
"""
Basic Commodity exchange.
"""
def __init__(self) -> None:
self.account={}
self.escrow={}
self.lme=LightMatchingEngine()
self.order_account_map={}
self.orders={}
self.executed_trades=[]
self.order_total_price={}
self.market_rate={}
self.best_ask={}
self.best_bid={}
pass
def add_to_account(self,account_id,resource,amount):
"""
Adds resources to account escrow
"""
#check if account exists
if account_id not in self.account:
self.account[account_id]={_bal: 0}
#check if ressource exists
if resource not in self.account[account_id]:
self.account[account_id][resource]=0
self.account[account_id][resource]+=amount
def remove_from_account(self,account_id,resource,amount) -> int:
"""
Remove resources from account. Returns amount retrieved
"""
#check if account exists
if account_id not in self.account:
self.account[account_id]={_bal: 0}
#check if ressource exists
if resource not in self.account[account_id]:
self.account[account_id][resource]=0
ret=amount
remain=self.account[account_id][resource]-amount
if remain<0:
ret=self.account[account_id][resource]
self.account[account_id][resource]=0
else:
self.account[account_id][resource]-=amount
return ret
def _move_to_escrow(self,account_id,resource,amount):
"""
Adds resources from account to escrow. Return true if done.
"""
if not self.check_account_resource(account_id,resource,amount):
return False
#check if account exists
if account_id not in self.escrow:
self.escrow[account_id]={_bal: 0}
#check if ressource exists
if resource not in self.escrow[account_id]:
self.escrow[account_id][resource]=0
self.escrow[account_id][resource]+=amount
self.account[account_id][resource]-=amount
return True
def _move_to_account(self,account_id,resource,amount):
"""
Move resources from escrow to account.
"""
ret=amount
self.escrow[account_id][resource]-=amount
if resource not in self.account[account_id]:
self.account[account_id][resource]=0
self.account[account_id][resource]+=amount
def check_account_resource(self,account_id,resource,amount):
"""
Checks if account has sufficient resources in inventory
"""
if account_id not in self.account:
self.account[account_id]={_bal: 0}
#check if ressource exists
if resource not in self.account[account_id]:
self.account[account_id][resource]=0
if self.account[account_id][resource]>=amount:
return True
return False
def submit_order(self,account_id,resource,amount,price,side :int) -> Order:
"""
Submits an order to the exchange if resources are sufficent.
Price is price per single item.
Returns an order if the order is active. Returns None if submit has failed.
"""
# calculate price for complete order fullfilment
full_price=price*amount
# Move resources into escrow
if side==Side.BUY:
escrow=self._move_to_escrow(account_id,_bal,full_price)
else:
escrow=self._move_to_escrow(account_id,resource,amount)
if not escrow:
# no sufficient resources
return None
# create order and execude any trades
order,trades=self.lme.add_order(resource,price,amount,side)
self.orders[order.order_id]=order
self.order_account_map[order.order_id]=account_id
self._execute_trades(trades)
return order
def _execute_trades(self, trades):
for i in trades:
self._execute_trade(i)
def _is_order_complete(self,order: Order):
return order.leaves_qty==0
def _execute_trade(self, trade: Trade):
account_id=self.order_account_map[trade.order_id]
# calculate price for trade fullfilment
full_price=trade.trade_price*trade.trade_qty
exprected_price=self.orders[trade.order_id].price*trade.trade_qty
price_diff=exprected_price-full_price
# add to order total
if trade.order_id not in self.order_total_price:
self.order_total_price[trade.order_id]=0
self.order_total_price[trade.order_id]+=full_price
# init escrow if needet
if trade.instmt not in self.escrow[account_id]:
self.escrow[account_id][trade.instmt]=0
# first edit escrow
if trade.trade_side==Side.BUY:
self.escrow[account_id][trade.instmt]+=trade.trade_qty
self.escrow[account_id][_bal]-=full_price
# move new resources to account
self._move_to_account(account_id,trade.instmt,trade.trade_qty)
# if deal was better then expected move money back
self._move_to_account(account_id,_bal,price_diff)
else:
self.escrow[account_id][trade.instmt]-=trade.trade_qty
self.escrow[account_id][_bal]+=full_price
# move new bal into account
self._move_to_account(account_id,_bal,full_price)
self.executed_trades.append(trade)
#update market rate
self.market_rate[trade.instmt]=trade.trade_price