Files
econ_emt/econ/agents/base_distribution_agent.py

130 lines
4.2 KiB
Python

from .base_agent import BaseAgent
from ..exchange import Exchange
from lightmatchingengine.lightmatchingengine import Order,Side
from abc import ABC
from decimal import *
class Base_Distribution_Agent(BaseAgent,ABC):
def __init__(self,simulation,business,resource,exchanges: list) -> None:
"""
Agent for distribute of resources.
business: Business to distribute resources for.
resource: Resource to distribute.
exchanges: list of exchanges to distribute resources to.
"""
self.business=business
self.resource=resource
self.exchanges=exchanges
self.orders={i: {} for i in range(len(self.exchanges))}
self.target=0
self.min_price=-1
self.max_batch_qty=10
self.tincome=0
self.tqty=0
self.income_offset=0
self.qty_offset=0
super().__init__(simulation)
def set_target(self,target: int):
"""
Sets the amount of resources the agent should keep in business inventory
"""
self.target=target
def set_price_min(self,price: int):
"""
Sets the min price the agent should distribute the resources for.
Set to -1 to disable minimum.
"""
self.min_price=price
def target_error(self):
"""
Returns the difference between target and current business inventory.
If err >0 the business is in surplus
If err < 0 then agent needs to distribute resources
"""
err=self.business.inventory[self.resource]-self.target
return err
def distribute_resource(self,price_per,amount,cx_id):
"""
distribute resource from selected exchange.
Return true if order has been placed.
"""
# Get exchange
cx=self.exchanges[cx_id]
if not self.business.inventory[self.resource]>=amount:
return False # we dont have enough balance
self.business.inventory[self.resource]-=amount
cx.add_to_account(self.id,self.resource,amount) # prepaid charge account for cx
order=cx.submit_order(self.id,self.resource,amount,price_per,Side.SELL)
if order==None: # Order failed
return False
self.orders[cx_id][order.order_id]=order
return order
def collect_balance_from_cxs(self):
"""
Collects resouces from account inventory in cxs.
"""
for cx in self.exchanges:
amount=cx.get_account_resource_amount(self.id,"balance")
cx.remove_from_account(self.id,"balance",amount)
self.business.balance+=amount
def collect_resource_from_cxs(self,resource):
"""
Collects resouces from account inventory in cxs.
"""
for cx in self.exchanges:
amount=cx.get_account_resource_amount(self.id,resource)
cx.remove_from_account(self.id,resource,amount)
self.business.inventory[resource]+=amount
def update_trades(self) -> list:
"""
Returns a list of all trades performed by this agent
"""
trades=[]
self.tqty=0
self.tincome=0
for cx_id in range(len(self.exchanges)):
cx=self.exchanges[cx_id]
orders=self.orders[cx_id]
if len(orders)>0:
for k,o in orders.items():
if k in cx.order_trades_map:
trades.extend(cx.order_trades_map[k])
self.trades=trades
for t in trades:
self.tqty+=t.trade_qty
self.tincome+=t.trade_qty*t.trade_price
self.tincome=round(self.tincome,2)
return trades
@property
def qty(self):
return self.tqty+self.qty_offset
@property
def income(self):
return self.tincome+self.income_offset
def confirm_distribution(self,dis_qty,step):
income_per=self.income/self.qty
income_to_confirm=income_per*dis_qty
self.income_offset-=income_to_confirm
self.qty_offset-=dis_qty
self.income_offset=round(self.income_offset,2)
def reset(self, episode):
self.qty_offset=0
self.income_offset=0
self.trades=[]
return super().reset(episode)