This commit is contained in:
2024-10-13 16:55:06 -04:00
parent 915f5673bc
commit 5db870244f

View File

@@ -60,7 +60,7 @@ struct Trader {
password: String, // hash(name..salt..password) password: String, // hash(name..salt..password)
id: usize, id: usize,
balances: HashMap<usize,FiNum>, // Maps Currency to Amount balances: HashMap<usize,FiNum>, // Maps Currency to Amount
order_finder: HashMap<usize,(usize,usize)>, order_finder: HashMap<usize,(usize,usize)>, // Maps OrderIDs to asset pairs (Order trees)
} }
#[derive(Clone)] #[derive(Clone)]
@@ -120,7 +120,7 @@ struct RoyaltyTree {
tree: Vec<Royalty>, tree: Vec<Royalty>,
next_entry: usize, next_entry: usize,
spare_change: FiNum, // Waiting to be distributed spare_change: FiNum, // Waiting to be distributed
order_finder: HashMap<usize,usize>, order_finder: HashMap<usize,usize>, // Maps OrderID to location (index) in the tree
} }
struct Royalty { struct Royalty {
@@ -356,7 +356,8 @@ struct Market {
orders: HashMap<(usize,usize),OrderQueue>, orders: HashMap<(usize,usize),OrderQueue>,
royalties: HashMap<usize,RoyaltyTree>, // Active orders that are accepting asset X. They receive royalties when someone makes an order to sell X royalties: HashMap<usize,RoyaltyTree>, // Active orders that are accepting asset X. They receive royalties when someone makes an order to sell X
royalty_rate: HashMap<usize,FiNum>, royalty_rate: HashMap<usize,FiNum>,
order_finder: HashMap<usize,(usize,usize)>, // To find an order, look in Orders.get(usize,usize) at position usize order_finder: HashMap<usize,(usize,usize)>, // Maps Order ID to an asset pair (in other systems, a "market.") From there you can look in self.orders.get((usize,usize)) which is an OrderQueue, and OrderQueues have a mapping from ID to position in the OrderQueue
order_count: usize,
next_order_id: usize, next_order_id: usize,
rng: StdRng, rng: StdRng,
} }
@@ -373,6 +374,7 @@ impl Market {
royalties: HashMap::new(), royalties: HashMap::new(),
royalty_rate: HashMap::new(), royalty_rate: HashMap::new(),
order_finder: HashMap::new(), order_finder: HashMap::new(),
order_count: 0,
next_order_id: 1, next_order_id: 1,
rng: StdRng::seed_from_u64(1u64), rng: StdRng::seed_from_u64(1u64),
}; };
@@ -393,6 +395,15 @@ impl Market {
println!(" {}: Orders {} Traders {} Total {} Should Be {}",self.number_to_name(*cur),acc_orders,acc_traders,acc,*amt); println!(" {}: Orders {} Traders {} Total {} Should Be {}",self.number_to_name(*cur),acc_orders,acc_traders,acc,*amt);
} }
} }
fn random_order_id(&mut self) -> Option<usize> {
let x=self.rng.gen_range(0..self.order_count);
let mut bottom=0;
for (pair,bucket) in &self.orders {
if x<bottom+bucket.v.len() { return Some(bucket.v[x-bottom].order_id) }
bottom+=bucket.v.len();
}
None
}
fn register_trader(&mut self, name:&str) -> usize { // Add error checking for inserting a trader twice fn register_trader(&mut self, name:&str) -> usize { // Add error checking for inserting a trader twice
let rval=self.traders.len(); let rval=self.traders.len();
self.trader_name2num.insert(String::from(name),self.traders.len()); self.trader_name2num.insert(String::from(name),self.traders.len());
@@ -503,11 +514,27 @@ impl Market {
self.traders[bids1.peek().owner].add_balance(asset_type0,asset0_paying); self.traders[bids1.peek().owner].add_balance(asset_type0,asset0_paying);
log.push(format!(" {} got {} {}, {} got {} {}",self.traders[bids0.peek().owner].name,asset1_paying,asset1.name, log.push(format!(" {} got {} {}, {} got {} {}",self.traders[bids0.peek().owner].name,asset1_paying,asset1.name,
self.traders[bids1.peek().owner].name,asset0_paying,asset0.name)); self.traders[bids1.peek().owner].name,asset0_paying,asset0.name));
if bids0.peek().sell_remain==FiNum::zero() { println!("Nope0!!!"); bids0.pop(); } // Stopped work here. Must fixup all the data structures for these pops. if bids0.peek().sell_remain==FiNum::zero() { println!("Nope0!!!"); bids0.pop(); self.order_count-=1; } // Stopped work here. Must fixup all the data structures for these pops.
if bids1.peek().sell_remain==FiNum::zero() { println!("Nope1!!!"); bids1.pop(); } if bids1.peek().sell_remain==FiNum::zero() { println!("Nope1!!!"); bids1.pop(); self.order_count-=1; }
} }
Result::ExecutedBatch(log) Result::ExecutedBatch(log)
} }
fn retract_order(&mut self, order_id:usize) -> Result {
let pair=self.order_finder.get(&order_id).unwrap();
let queue=self.orders.get_mut(pair).unwrap();
let queue_index=*queue.order_finder.get(&order_id).unwrap();
let order=&queue.v[queue_index];
println!("Order owner is {}",order.owner);
// Remove from royalties
let rt=self.royalties.get_mut(&pair.0).unwrap();
rt.remove_order_id(order_id);
// Remove from order_finder
self.order_finder.remove(&order_id);
// Remove from orders
queue.remove(queue_index);
self.order_count-=1;
Result::RetractedOrder(order_id)
}
fn make_order(&mut self, owner:usize, sell_type:usize, buy_type:usize, sell_qty_initial:FiNum, buy_qty_initial:FiNum, execute_if_possible:bool) -> Result { fn make_order(&mut self, owner:usize, sell_type:usize, buy_type:usize, sell_qty_initial:FiNum, buy_qty_initial:FiNum, execute_if_possible:bool) -> Result {
let mut log:Vec<String>=Vec::new(); let mut log:Vec<String>=Vec::new();
let initial_balance=self.traders[owner].get_balance(sell_type); let initial_balance=self.traders[owner].get_balance(sell_type);
@@ -562,6 +589,7 @@ impl Market {
self.order_finder.remove(&top_order.order_id); self.order_finder.remove(&top_order.order_id);
self.traders[top_order.owner].order_finder.remove(&top_order.order_id); self.traders[top_order.owner].order_finder.remove(&top_order.order_id);
self.orders.get_mut(&ap).unwrap().pop(); // This removes id (which is stored as part of the Order) from self.order's finder self.orders.get_mut(&ap).unwrap().pop(); // This removes id (which is stored as part of the Order) from self.order's finder
self.order_count-=1;
} else { } else {
top_order.sell_remain-=qty; top_order.sell_remain-=qty;
} }
@@ -590,6 +618,7 @@ impl Market {
// Insert the new order in the priority queue (OrderQueue) // Insert the new order in the priority queue (OrderQueue)
let neworder=Order { owner:owner, sell_qty:sell_qty_remain, sell_remain:sell_qty_remain, buy_qty:buy_qty, royalty_remain:royalty1_qty, commission_remain:commission1_qty, order_id:id }; let neworder=Order { owner:owner, sell_qty:sell_qty_remain, sell_remain:sell_qty_remain, buy_qty:buy_qty, royalty_remain:royalty1_qty, commission_remain:commission1_qty, order_id:id };
bids.insert(neworder); bids.insert(neworder);
self.order_count+=1;
self.order_finder.insert(id,(sell_type,buy_type)); self.order_finder.insert(id,(sell_type,buy_type));
self.traders[owner].sub_balance(sell_type,sell_qty_remain); self.traders[owner].sub_balance(sell_type,sell_qty_remain);
self.traders[0].add_balance(sell_type,commission0_qty); self.traders[0].add_balance(sell_type,commission0_qty);
@@ -626,7 +655,7 @@ impl PartialEq for Order {
struct OrderQueue { struct OrderQueue {
v: Vec<Order>, v: Vec<Order>,
order_finder: HashMap<usize,usize>, // Maps IDs to locations in v order_finder: HashMap<usize,usize>, // Maps OrderIDs to locations in v
} }
impl OrderQueue { impl OrderQueue {
@@ -678,13 +707,16 @@ impl OrderQueue {
self.bubble_up(self.v.len()-1); self.bubble_up(self.v.len()-1);
} }
fn pop(&mut self) -> Option<Order> { fn pop(&mut self) -> Option<Order> {
if self.v.len()==0 { None } self.remove(0)
}
fn remove(&mut self, pos: usize) -> Option<Order> {
if self.v.len()<=pos { None }
else { else {
let end=self.v.len()-1; let end=self.v.len()-1;
self.v.swap(0,end); self.v.swap(pos,end);
self.order_finder.remove(&self.v[end].order_id); self.order_finder.remove(&self.v[end].order_id);
let rval=self.v.pop(); let rval=self.v.pop();
self.trickle_down(0); self.trickle_down(pos);
rval rval
} }
} }
@@ -704,11 +736,15 @@ impl Market {
1 => Command::AddFunds { user_id: self.rng.gen_range(1..self.traders.len()), 1 => Command::AddFunds { user_id: self.rng.gen_range(1..self.traders.len()),
asset_id: self.rng.gen_range(0..self.assets.len()), asset_id: self.rng.gen_range(0..self.assets.len()),
amt: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), }, amt: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), },
2 => Command::Order { user_id: self.rng.gen_range(1..self.traders.len()), 2 => Command::AddFunds { user_id: self.rng.gen_range(1..self.traders.len()),
asset_id: self.rng.gen_range(0..self.assets.len()),
amt: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), },
3 => Command::Order { user_id: self.rng.gen_range(1..self.traders.len()),
sell_type: self.rng.gen_range(0..self.assets.len()), sell_type: self.rng.gen_range(0..self.assets.len()),
sell_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), sell_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)),
buy_type: self.rng.gen_range(0..self.assets.len()), buy_type: self.rng.gen_range(0..self.assets.len()),
buy_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), }, buy_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), },
// 4 => Command::RetractOrder { {*}
_ => Command::Error("This can never happen".to_string()), _ => Command::Error("This can never happen".to_string()),
} }
} }
@@ -964,7 +1000,7 @@ impl Market {
self.make_order(*user_id,*sell_type,*buy_type,*sell_qty,*buy_qty,false) self.make_order(*user_id,*sell_type,*buy_type,*sell_qty,*buy_qty,false)
} }
Command::RetractOrder { order_id } => { Command::RetractOrder { order_id } => {
Result::Error(format!("Retract Order {} not yet implemented.",order_id)) self.retract_order(*order_id)
} }
Command::ExecuteBatch { asset_type0, strike0, asset_type1, strike1 } => { Command::ExecuteBatch { asset_type0, strike0, asset_type1, strike1 } => {
self.execute_batch(*asset_type0, *strike0, *asset_type1, *strike1) self.execute_batch(*asset_type0, *strike0, *asset_type1, *strike1)
@@ -1037,6 +1073,7 @@ fn tokens_to_command(m: &Market, logged_in: usize, tokens: Vec<&str>,line: &str)
if !m.order_finder.contains_key(&order_id) { return Command::Error(format!("Order not found: {}",p_order_id)) } if !m.order_finder.contains_key(&order_id) { return Command::Error(format!("Order not found: {}",p_order_id)) }
let trader=&m.traders[logged_in]; let trader=&m.traders[logged_in];
let order_type=trader.order_finder.get(&order_id); let order_type=trader.order_finder.get(&order_id);
println!("Order_type {:?}",order_type);
let order_queue=m.orders.get(order_type.expect("Retrieving Order Queue")); let order_queue=m.orders.get(order_type.expect("Retrieving Order Queue"));
Command::RetractOrder { order_id: order_id } Command::RetractOrder { order_id: order_id }
} }
@@ -1089,6 +1126,7 @@ fn interactive(m: &mut Market, mut out: Option<File>) {
let tokens: Vec<&str> = input.split_whitespace().collect(); let tokens: Vec<&str> = input.split_whitespace().collect();
let cmd:Command=match tokens.as_slice() { let cmd:Command=match tokens.as_slice() {
["dump"] => { m.dump(); Command::None }, ["dump"] => { m.dump(); Command::None },
["randomorder"] => { println!("Random OrderID: {:?}",m.random_order_id()); Command::None }
["login", username] => { ["login", username] => {
if let Some(t)=m.trader_name2num.get_mut(*username) { trader=*t; println!("Logged in as {}",m.traders[trader].name) } else { println!("Trader {} not found.",username) } if let Some(t)=m.trader_name2num.get_mut(*username) { trader=*t; println!("Logged in as {}",m.traders[trader].name) } else { println!("Trader {} not found.",username) }
Command::None Command::None