adding some basic exchange
This commit is contained in:
Binary file not shown.
+2
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user