changes
This commit is contained in:
60
src/main.rs
60
src/main.rs
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user