reading fucking cells

This commit is contained in:
2023-01-24 15:15:53 +01:00
parent 89dc8ed54a
commit be83cbd988
31 changed files with 340 additions and 80 deletions
+16
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
kind: demand
spec:
- name: basic
res:
- 'Food': 1
+17
View File
@@ -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
+15
View File
@@ -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
+1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
+21 -10
View File
@@ -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"]
+12 -3
View File
@@ -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
+2 -1
View File
@@ -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):
+36 -14
View File
@@ -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()
+28 -4
View File
@@ -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()
+7 -3
View File
@@ -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)
+1
View File
@@ -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.
+69
View File
@@ -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
+10
View File
@@ -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
-33
View File
@@ -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,
}
},
]
+46
View File
@@ -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
View File
@@ -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
View File
@@ -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
+15 -6
View File
@@ -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,{