reading fucking cells
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
kind: commodity
|
||||
spec:
|
||||
- name: "Gem"
|
||||
max_world_price: 100
|
||||
|
||||
- name: "Food"
|
||||
max_world_price: 5
|
||||
|
||||
|
||||
- name: "Grain"
|
||||
max_world_price: 1
|
||||
|
||||
|
||||
- name: "Fruit"
|
||||
max_world_price: 1
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
kind: demand
|
||||
spec:
|
||||
- name: basic
|
||||
res:
|
||||
- 'Food': 1
|
||||
@@ -0,0 +1,17 @@
|
||||
kind: production
|
||||
spec:
|
||||
- name: Food
|
||||
amount: 1
|
||||
prod:
|
||||
- "Grain": 1
|
||||
- "Fruit": 1
|
||||
|
||||
- name: Grain
|
||||
amount: 1
|
||||
prod:
|
||||
- Raw_Agriculture_Plot: 1
|
||||
|
||||
- name: Fruit
|
||||
amount: 1
|
||||
prod:
|
||||
- Raw_Agriculture_Plot: 1
|
||||
@@ -0,0 +1,15 @@
|
||||
kind: world
|
||||
spec:
|
||||
- name: gems
|
||||
res:
|
||||
- 'Raw_Gem': 15
|
||||
|
||||
- name: grass
|
||||
res:
|
||||
- 'Raw_Agriculture_Plot': 0.3
|
||||
|
||||
- name: forrest
|
||||
res:
|
||||
- 'Raw_Agriculture_Plot': 1
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,12 +5,19 @@ class AutoProductionAgent(BaseAgent):
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self,sim,business) -> None:
|
||||
def __init__(self,sim,business,worker=1,employment_rate=0) -> None:
|
||||
super().__init__(sim)
|
||||
self.business=business
|
||||
self.prod=business.production
|
||||
self.worker=worker
|
||||
self.employment_rate=employment_rate
|
||||
self.employment_index=worker
|
||||
|
||||
|
||||
def set_worker(self,workers):
|
||||
if workers>1:
|
||||
self.worker=workers
|
||||
else:
|
||||
self.worker=1
|
||||
|
||||
def can_produce(self):
|
||||
# If can produce item
|
||||
@@ -19,11 +26,15 @@ class AutoProductionAgent(BaseAgent):
|
||||
return False
|
||||
return True
|
||||
|
||||
def tick(self):
|
||||
if not self.can_produce():
|
||||
return
|
||||
# remove cost from inventory
|
||||
for k,cost in self.prod["craft"].items():
|
||||
self.business.inventory[k]-=cost
|
||||
# add commodity
|
||||
self.business.inventory[self.prod['name']]+=self.prod["amount"]
|
||||
def tick(self,step,epi):
|
||||
for i in range(self.worker):
|
||||
if not self.can_produce():
|
||||
self.employment_index-=self.employment_rate
|
||||
continue
|
||||
self.employment_index+=self.employment_rate
|
||||
self.set_worker(int(self.employment_index))
|
||||
# remove cost from inventory
|
||||
for k,cost in self.prod["craft"].items():
|
||||
self.business.inventory[k]-=cost
|
||||
# add commodity
|
||||
self.business.inventory[self.prod['name']]+=self.prod["amount"]
|
||||
|
||||
@@ -9,9 +9,18 @@ class BaseAgent(ABC):
|
||||
"""
|
||||
self.id=uuid.uuid4()
|
||||
self.simulation=simulation
|
||||
simulation.register_tick(self.id,self.tick)
|
||||
simulation.register_agent(self.id,self.tick,self.reset)
|
||||
pass
|
||||
def tick(self):
|
||||
def tick(self,tick,episode):
|
||||
"""
|
||||
Tick method for simulation to call to execute selected action
|
||||
"""
|
||||
"""
|
||||
assert "No Tick method has been provided"
|
||||
pass
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Resets agent to new episode.
|
||||
"""
|
||||
assert "No reset method has been provided"
|
||||
pass
|
||||
@@ -16,6 +16,7 @@ class Base_Aquire_Agent(BaseAgent,ABC):
|
||||
self.exchanges=exchanges
|
||||
self.orders={i: {} for i in range(len(self.exchanges))}
|
||||
self.target=0
|
||||
self.trades=[]
|
||||
self.max_price=-1
|
||||
super().__init__(simulation)
|
||||
|
||||
@@ -61,7 +62,7 @@ class Base_Aquire_Agent(BaseAgent,ABC):
|
||||
if order==None: # Order failed
|
||||
return False
|
||||
self.orders[cx_id][order.order_id]=order
|
||||
|
||||
self.update_trades()
|
||||
return order
|
||||
|
||||
def collect_balance_from_cxs(self):
|
||||
|
||||
@@ -8,26 +8,39 @@ class Price_Believe_Aquire_Agent(Base_Aquire_Agent):
|
||||
super().__init__(simulation, business, resource, exchanges)
|
||||
self.lr=lr
|
||||
self.max_price_adj_rate=max_price_adj_rate
|
||||
self.price_believe=-1
|
||||
self.price_believe={i: -1 for i in range(len(self.exchanges))}
|
||||
self.open_orders={i: [] for i in range(len(self.exchanges))}
|
||||
self.open_qty=0
|
||||
|
||||
|
||||
def tick(self):
|
||||
def tick(self,tick,episode):
|
||||
if self.price_believe==-1:
|
||||
self.price_believe=self.max_price
|
||||
|
||||
order_error=self.open_qty+self.target_error()
|
||||
if order_error<0:
|
||||
# aquire based on current price belive
|
||||
order=self.order_resource(self.price_believe,order_error*-1,0)
|
||||
cx_id=self.select_best_cx()
|
||||
order=self.order_resource(self.price_believe[cx_id],order_error*-1,cx_id)
|
||||
if not order==None:
|
||||
self.register_order(0,order)
|
||||
else:
|
||||
# order failed .. we need to adjust our price believe
|
||||
self.update_believe(-1)
|
||||
# order failed due to missing balance.. we need to adjust our price believe
|
||||
self.collect_balance_from_cxs()
|
||||
self.collect_resource_from_cxs(self.resource)
|
||||
self.update_believe(cx_id,-1)
|
||||
self.tick_open_orders()
|
||||
|
||||
|
||||
def select_best_cx(self):
|
||||
best_id=0
|
||||
best=0
|
||||
for cx_id in range(len(self.exchanges)):
|
||||
cx=self.exchanges[cx_id]
|
||||
potential=cx.total_supply[self.resource]*self.price_believe[cx_id]
|
||||
if potential<best:
|
||||
best=potential
|
||||
best_id=cx_id
|
||||
return best_id
|
||||
|
||||
def register_order(self,cx_id,order):
|
||||
self.open_orders[cx_id].append({
|
||||
@@ -61,19 +74,28 @@ class Price_Believe_Aquire_Agent(Base_Aquire_Agent):
|
||||
# timeout
|
||||
cx.cancel_order(i["id"])
|
||||
self.collect_balance_from_cxs()
|
||||
self.collect_resource_from_cxs()
|
||||
self.collect_resource_from_cxs(self.resource)
|
||||
self.update_believe(1)
|
||||
self.open_orders[cx_id].remove(i)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def update_believe(self,modifier):
|
||||
def update_believe(self,cx_id,modifier):
|
||||
"""
|
||||
Updates the believe based on the modifier.
|
||||
If positive will add lr to believe
|
||||
If negative will sub lr to believe
|
||||
"""
|
||||
self.price_believe+=modifier*self.lr
|
||||
self.price_believe[cx_id]+=modifier*self.lr
|
||||
|
||||
def reset(self):
|
||||
# Clean shop for today
|
||||
for cx_id in range(len(self.exchanges)):
|
||||
cx=self.exchanges[cx_id]
|
||||
cx_orders=self.open_orders[cx_id]
|
||||
for i in cx_orders:
|
||||
cx.cancel_order(i["id"])
|
||||
self.collect_balance_from_cxs()
|
||||
self.collect_resource_from_cxs(self.resource)
|
||||
# book keeping
|
||||
self.update_trades()
|
||||
|
||||
return super().reset()
|
||||
@@ -19,11 +19,21 @@ class Price_Believe_Distribiute_Agent(Base_Distribution_Agent):
|
||||
order_error=self.target_error()
|
||||
if order_error>0:
|
||||
# aquire based on current price belive
|
||||
order=self.distribute_resource(self.price_believe,order_error,0)
|
||||
cx_id=self.select_best_cx()
|
||||
order=self.distribute_resource(self.price_believe,order_error,cx_id)
|
||||
self.register_order(0,order)
|
||||
self.tick_open_orders()
|
||||
|
||||
|
||||
def select_best_cx(self):
|
||||
best_id=0
|
||||
best=0
|
||||
for cx_id in range(len(self.exchanges)):
|
||||
cx=self.exchanges[cx_id]
|
||||
potential=cx.total_supply[self.resource]*self.price_believe[cx_id]
|
||||
if potential>best:
|
||||
best=potential
|
||||
best_id=cx_id
|
||||
return best_id
|
||||
|
||||
def register_order(self,cx_id,order):
|
||||
self.open_orders[cx_id].append({
|
||||
@@ -66,10 +76,24 @@ class Price_Believe_Distribiute_Agent(Base_Distribution_Agent):
|
||||
|
||||
|
||||
|
||||
def update_believe(self,modifier):
|
||||
def update_believe(self,cx_id,modifier):
|
||||
"""
|
||||
Updates the believe based on the modifier.
|
||||
If positive will add lr to believe
|
||||
If negative will sub lr to believe
|
||||
"""
|
||||
self.price_believe+=modifier*self.lr
|
||||
self.price_believe[cx_id]+=modifier*self.lr
|
||||
|
||||
def reset(self):
|
||||
# Clean shop for today
|
||||
for cx_id in range(len(self.exchanges)):
|
||||
cx=self.exchanges[cx_id]
|
||||
cx_orders=self.open_orders[cx_id]
|
||||
for i in cx_orders:
|
||||
cx.cancel_order(i["id"])
|
||||
self.collect_balance_from_cxs()
|
||||
self.collect_resource_from_cxs(self.resource)
|
||||
# book keeping
|
||||
self.update_trades()
|
||||
|
||||
return super().reset()
|
||||
@@ -3,19 +3,23 @@ from ..agents.price_believe_aquire import Price_Believe_Aquire_Agent
|
||||
from ..agents.price_believe_distribute import Price_Believe_Distribiute_Agent
|
||||
from ..agents.autoproduction import AutoProductionAgent
|
||||
class Price_Believe_Business(Business):
|
||||
def __init__(self, id, production, balance,exchange,simulation) -> None:
|
||||
def __init__(self, id, production, balance,exchange,simulation) -> None:
|
||||
super().__init__(id, production, balance)
|
||||
|
||||
self.distribute=Price_Believe_Distribiute_Agent(simulation,self,production["name"],exchange,1,50)
|
||||
self.distribute=Price_Believe_Distribiute_Agent(simulation,self,production["name"],exchange,0.1,50)
|
||||
self.craft=AutoProductionAgent(simulation,self)
|
||||
self.aquire={}
|
||||
for k,v in production["craft"].items():
|
||||
a=Price_Believe_Aquire_Agent(simulation,self,k,exchange,1,50)
|
||||
a.set_target(v*10)
|
||||
a.set_target(v*2)
|
||||
a.set_price_max(10)
|
||||
self.aquire[k]=a
|
||||
self.distribute.set_price_min(10)
|
||||
self.distribute.set_target(0)
|
||||
|
||||
def step_business_decisions(self):
|
||||
for k,v in self.production["craft"].items():
|
||||
modifier=self.craft.worker+1
|
||||
self.aquire[k].set_target(v*modifier)
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -21,5 +21,6 @@ class Business(ABC):
|
||||
pass
|
||||
|
||||
def step_business_decisions(self):
|
||||
assert "no business decision method has been created"
|
||||
pass
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
from ..exchange import Exchange
|
||||
from ..commoditys import commoditys as cm
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Cell:
|
||||
"""
|
||||
A cell is the basic procedual structure of this simulation. If a cell contains pop then this Cell will have a local market.
|
||||
If the cell is contained in a province then the cell will have a
|
||||
"""
|
||||
name=None # Unique ID/Name of the cell
|
||||
loc_x=0
|
||||
loc_y=0
|
||||
area=1
|
||||
pop=0 # Population of the cell
|
||||
demand_tags=[] # Demands by 1 pop
|
||||
world_tags=[] # Resources provided by cell each episode
|
||||
demand={}
|
||||
world={}
|
||||
exchange: None
|
||||
|
||||
def __init__(self,name,x,y,area,pop,demand,world) -> None:
|
||||
self.name=name
|
||||
self.loc_x=x
|
||||
self.loc_y=y
|
||||
self.area=area
|
||||
self.pop=pop*1000
|
||||
self.demand_tags=demand
|
||||
self.demand={}
|
||||
self.world_tags=world
|
||||
self.world={}
|
||||
|
||||
if pop>0:
|
||||
self.exchange=Exchange()
|
||||
# build per person demand
|
||||
for tag in self.demand_tags:
|
||||
d=cm.demand_tags[tag]
|
||||
for dem in d:
|
||||
k=list(dem.keys())[0]
|
||||
v=dem[k]
|
||||
if k not in self.demand:
|
||||
self.demand[k]=v*pop
|
||||
else:
|
||||
self.demand[k]+=v*pop
|
||||
for tag in self.world_tags:
|
||||
d=cm.world_tags[tag]
|
||||
for wor in d:
|
||||
k=list(wor.keys())[0]
|
||||
v=wor[k]
|
||||
if k not in self.world:
|
||||
self.world[k]=v*area
|
||||
else:
|
||||
self.world[k]+=v*area
|
||||
|
||||
|
||||
def create_cells_from_world_cells(cells) -> list:
|
||||
"""
|
||||
Creates cells based on a list of cells provided from a world
|
||||
"""
|
||||
ret_cells=[]
|
||||
# For now make it very simple
|
||||
for i in cells:
|
||||
cell=Cell(i["i"],i["p"][0],i["p"][1],i["area"],i["pop"],["basic"],["grass"])
|
||||
ret_cells.append(cell)
|
||||
|
||||
return ret_cells
|
||||
@@ -0,0 +1,10 @@
|
||||
import json
|
||||
|
||||
world = {}
|
||||
|
||||
def load_world(filepath):
|
||||
file= open(filepath, 'r',encoding='UTF-8')
|
||||
data=file.readlines()
|
||||
global world
|
||||
world = json.loads(data[0])
|
||||
return world
|
||||
@@ -1,33 +0,0 @@
|
||||
commoditys=[
|
||||
{
|
||||
'name': 'Gem',
|
||||
'amount': 4,
|
||||
'craft': {
|
||||
'Raw_Gem': 4,
|
||||
'Tool_Gem': 0.2,
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Tool_Gem',
|
||||
'amount': 1,
|
||||
'craft': {
|
||||
'Stone': 1,
|
||||
'Wood': 1,
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Wood',
|
||||
'amount': 1,
|
||||
'craft': {
|
||||
'Raw_Wood': 1,
|
||||
}
|
||||
},
|
||||
{
|
||||
'name': 'Stone',
|
||||
'amount': 1,
|
||||
'craft': {
|
||||
'Raw_Stone': 1,
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
import yaml
|
||||
|
||||
|
||||
# create an empty dictionary to store the demand tags
|
||||
demand_tags = {} # demand tags with demands
|
||||
world_tags = {} # available resources tags with resources available
|
||||
commoditys = {} # commoditys by name
|
||||
productions = {} # list of production rules by commodity name
|
||||
productions_uses = {} # list of productions that are a key commodity
|
||||
data={}
|
||||
def search_yaml_files(directory = "db"):
|
||||
"""
|
||||
Load all tags from the db
|
||||
"""
|
||||
# iterate through the YAML files in the directory
|
||||
for filename in os.listdir(directory):
|
||||
filepath = os.path.join(directory, filename)
|
||||
if os.path.isdir(filepath):
|
||||
search_yaml_files(filepath)
|
||||
elif filename.endswith(".yml"):
|
||||
# open and read the YAML file
|
||||
with open(filepath, 'r') as file:
|
||||
data = yaml.safe_load(file)
|
||||
# check the kind of tag
|
||||
if data['kind'] == "world":
|
||||
for tag in data['spec']:
|
||||
world_tags[tag['name']] = tag['res']
|
||||
elif data['kind'] == "demand":
|
||||
for tag in data['spec']:
|
||||
demand_tags[tag['name']] = tag['res']
|
||||
elif data['kind'] == "commodity":
|
||||
for comm in data['spec']:
|
||||
commoditys[comm['name']] = comm
|
||||
elif data['kind'] == "production":
|
||||
for comm in data['spec']:
|
||||
if comm['name'] not in productions:
|
||||
productions[comm['name']]=[]
|
||||
productions[comm['name']].append(comm)
|
||||
for comp in comm["prod"]:
|
||||
k=list(comp.keys())[0]
|
||||
if k not in productions_uses:
|
||||
productions_uses[k]=[]
|
||||
productions_uses[k].append(comm)
|
||||
|
||||
|
||||
+23
-4
@@ -17,6 +17,10 @@ class Exchange():
|
||||
self.market_rate={}
|
||||
self.best_ask={}
|
||||
self.best_bid={}
|
||||
self.total_demand={}
|
||||
self.demand={}
|
||||
self.total_supply={}
|
||||
self.supply={}
|
||||
pass
|
||||
|
||||
def add_to_account(self,account_id,resource,amount):
|
||||
@@ -116,13 +120,13 @@ class Exchange():
|
||||
# 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)
|
||||
self.calculate_best_price(resource)
|
||||
self.calculate_resource_metrics(resource)
|
||||
return order
|
||||
|
||||
def cancel_order(self,order_id):
|
||||
@@ -203,11 +207,26 @@ class Exchange():
|
||||
self.market_rate[trade.instmt]=trade.trade_price
|
||||
|
||||
|
||||
def calculate_best_price(self, resource):
|
||||
def calculate_resource_metrics(self, resource):
|
||||
order_book = self.lme.order_books.setdefault(resource, OrderBook())
|
||||
best_bid = max(order_book.bids.keys()) if len(order_book.bids) > 0 else None
|
||||
best_ask = max(order_book.asks.keys()) if len(order_book.asks) > 0 else None
|
||||
|
||||
self.total_demand[resource]=0
|
||||
self.demand[resource]={}
|
||||
for k,v in order_book.bids.items():
|
||||
self.demand[resource][k]=0
|
||||
for o in v:
|
||||
self.demand[resource][k]+=o.qty
|
||||
self.total_demand[resource]+=o.qty
|
||||
self.supply[resource]={}
|
||||
self.total_supply[resource]=0
|
||||
for k,v in order_book.asks.items():
|
||||
self.supply[resource][k]=0
|
||||
for o in v:
|
||||
self.supply[resource][k]+=o.qty
|
||||
self.total_supply[resource]+=o.qty
|
||||
|
||||
|
||||
self.best_ask[resource]=best_ask
|
||||
self.best_bid[resource]=best_bid
|
||||
|
||||
|
||||
+16
-2
@@ -5,6 +5,9 @@ class Simulation():
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
self.tick_funcs={}
|
||||
self.reset_funcs={}
|
||||
self.tick_count=0
|
||||
self.episode_count=0
|
||||
pass
|
||||
|
||||
def seed(self,a):
|
||||
@@ -12,9 +15,10 @@ class Simulation():
|
||||
Sets the random seed
|
||||
"""
|
||||
random.seed(a)
|
||||
def register_tick(self,id,tickfunc):
|
||||
def register_agent(self,id,tickfunc,resetfunc):
|
||||
|
||||
self.tick_funcs[id]=tickfunc
|
||||
self.reset_funcs[id]=resetfunc
|
||||
|
||||
def tick_random_order(self):
|
||||
"""
|
||||
@@ -24,4 +28,14 @@ class Simulation():
|
||||
random.shuffle(keys)
|
||||
for k in keys:
|
||||
fun=self.tick_funcs[k]
|
||||
fun()
|
||||
fun(self.tick_count,self.episode_count)
|
||||
self.tick_count+=1
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
Resets all agents to new Episode
|
||||
"""
|
||||
for k,v in self.reset_funcs.items():
|
||||
v(self.episode_count)
|
||||
self.tick_count=0
|
||||
self.episode_count+=1
|
||||
@@ -2,21 +2,30 @@ from lightmatchingengine.lightmatchingengine import LightMatchingEngine,Side,Tra
|
||||
from econ.exchange import Exchange
|
||||
from econ.simulation import Simulation
|
||||
from econ.business.Price_Believe_Business import Price_Believe_Business
|
||||
from econ.commoditys import commoditys
|
||||
from econ.cells import db, cell
|
||||
|
||||
db.load_world("db/world.json")
|
||||
|
||||
commoditys.search_yaml_files()
|
||||
|
||||
cell_realm=[]
|
||||
|
||||
for c in db.world["cells"]["cells"]:
|
||||
if c["province"]==187:
|
||||
cell_realm.append(c)
|
||||
|
||||
cells=cell.create_cells_from_world_cells(cell_realm)
|
||||
|
||||
|
||||
w="world"
|
||||
cx=Exchange()
|
||||
cxs=[cx]
|
||||
# Init World
|
||||
cx.add_to_account(w,"balance",15000)
|
||||
cx.add_to_account(w,"Raw_Wood",1000)
|
||||
cx.add_to_account(w,"Raw_Stone",1000)
|
||||
cx.submit_order(w,"Raw_Stone",1000,0,Side.SELL)
|
||||
cx.submit_order(w,"Raw_Wood",1000,0,Side.SELL)
|
||||
|
||||
# Create Demand
|
||||
cx.submit_order(w,"Wood",10,10,Side.BUY)
|
||||
cx.submit_order(w,"Wood",0,1000,Side.BUY)
|
||||
cx.submit_order(2,"Gem",1,10,Side.SELL)
|
||||
|
||||
sim=Simulation()
|
||||
bus=Price_Believe_Business(1,{
|
||||
|
||||
Reference in New Issue
Block a user