This commit is contained in:
2025-01-05 22:34:32 -05:00
parent 5db870244f
commit 1585f39c3f
4 changed files with 162 additions and 82 deletions

View File

@@ -46,11 +46,11 @@ use std::fs::OpenOptions;
use std::path::Path;
use std::io::{self, BufRead, Write};
use std::env;
//use std::collections::HashMap;
use std::collections::HashMap;
use std::cmp::Ordering;
use rand::prelude::*;
use rand::rngs::StdRng;
use hashbrown::HashMap;
//use hashbrown::HashMap;
mod finum;
use finum::FiNum;
@@ -166,7 +166,7 @@ impl RoyaltyTree {
0
} else {
let c0=self.count_here_below(wt_left (index).unwrap());
let c1=self.count_here_below(wt_right(index).unwrap());
let c1=self.count_here_below(wt_right(index).unwrap());
c0+c1
}
}
@@ -200,17 +200,23 @@ impl RoyaltyTree {
self.tree[index].lazy=FiNum::zero();
} else {
let lazy=self.tree[index].lazy;
// println!("Index is {}, lazy.0 {}",index,lazy.value());
// println!("Index is {}, lazy.0 {}",index,lazy.serialize());
// self.raw_dump();
let d1=if lazy>0.into() { lazy*self.weight_here(index)/self.weight_here_below(index) } else { FiNum::zero() };
let d02=lazy-d1;
let index_left =wt_left (index).unwrap();
let index_right=wt_right(index).unwrap();
let d0=if d02>0.into() { d02*self.weight_here_below(index_left)/self.weight_below(index) } else { FiNum::zero() };
let d2=d02-d0;
self.sanity();
if !self.weight_here_below(index_left ).is_zero() { self.tree[index_left ].lazy+=d0; } else { self.spare_change+=d0; }
if !self.weight_here_below(index_right).is_zero() { self.tree[index_right].lazy+=d2; } else { self.spare_change+=d2; }
// println!("D02 is {}, self.weight_here_below({}) is {}, self.weight_below({}) is {}",d02.serialize(),index_left,self.weight_here_below(index_left),index,self.weight_below(index));
if self.weight_below(index)>0.into() {
let d0=if d02>0.into() { d02*self.weight_here_below(index_left)/self.weight_below(index) } else { FiNum::zero() };
let d2=d02-d0;
self.sanity();
if !self.weight_here_below(index_left ).is_zero() { self.tree[index_left ].lazy+=d0; } else { self.spare_change+=d0; }
if !self.weight_here_below(index_right).is_zero() { self.tree[index_right].lazy+=d2; } else { self.spare_change+=d2; }
}
else {
self.spare_change+=d02;
}
self.tree[index].acc+=d1;
self.tree[index].lazy=FiNum::zero();
}
@@ -242,10 +248,10 @@ impl RoyaltyTree {
}
// We really need two methods: remove an order and redistribute, remove some and return captured amount
fn remove_order_id(&mut self, id: usize) { // And zero out in the tree
let pos=*self.order_finder.get(&id).unwrap();
self.order_finder.remove(&id);
let weight=self.weight_here(pos);
self.sub_weight(pos,weight);
if let Some(pos)=self.order_finder.remove(&id) {
let weight=self.weight_here(pos);
self.sub_weight(pos,weight);
}
}
fn random_order_id(&self, rng: &mut rand::rngs::StdRng) -> Option<usize> {
if self.tree.len()==0 { return None }
@@ -468,7 +474,17 @@ impl Market {
for index in 0..self.assets.len() {
let tot=self.royalties.get(&index).unwrap().acc_total();
println!(" For {}: {}",self.number_to_asset(index).name,tot);
}
for indexr in 0..self.royalties.get(&index).unwrap().tree.len() {
// let roy=self.royalties.get(&index).unwrap().get_royalty(indexr);
println!(" Index {} Count {} Weight {} Lazy {} Acc {} Royalty",
indexr,
self.royalties.get(&index).unwrap().tree[indexr].count,
self.royalties.get(&index).unwrap().tree[indexr].weight,
self.royalties.get(&index).unwrap().tree[indexr].lazy,
self.royalties.get(&index).unwrap().tree[indexr].acc);
// self.royalties.get(&index).unwrap().get_royalty(indexr));
}
}
println!("Trader Balances:");
for t in &self.traders {
println!(" Trader {}: {}",t.id,t.name);
@@ -492,7 +508,7 @@ impl Market {
}
}
}
fn execute_batch(&mut self, asset_type0: usize, strike0: FiNum, asset_type1: usize, strike1: FiNum) -> Result {
/* fn execute_batch(&mut self, asset_type0: usize, strike0: FiNum, asset_type1: usize, strike1: FiNum) -> Result {
let mut log:Vec<String>=Vec::new();
let asset0=self.number_to_asset(asset_type0);
let asset1=self.number_to_asset(asset_type1);
@@ -500,7 +516,7 @@ impl Market {
println!("Executing batch {} {} <-> {} {}",strike0,asset0.name,strike1,asset1.name);
let ap0=(asset_type0,asset_type1);
let ap1=(asset_type1,asset_type0);
let [bids0,bids1]=self.orders.get_many_mut([&ap0, &ap1]).unwrap();
let [bids0,bids1]=self.orders.get_many_mut([&ap0, &ap1]).unwrap(); // There's a workaround for this where you remove and reinsert the keys.
while !bids0.empty() && !bids1.empty()
&& bids0.peek().sell_qty/bids0.peek().buy_qty>=strike0/strike1
&& bids1.peek().sell_qty/bids1.peek().buy_qty>=strike1/strike0 {
@@ -519,6 +535,7 @@ impl Market {
}
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();
@@ -567,7 +584,7 @@ impl Market {
let cq0=commission0_qty*pay_qty/sell_qty_initial;
let rq1=royalty1_qty *pay_qty/sell_qty_initial;
let cq1=commission1_qty*pay_qty/sell_qty_initial;
println!("Transact at ask rate. Qty={} elt.sell_remain={} elt.royalty_remain={} elt.commission_remain={}",qty,elt.sell_remain,elt.royalty_remain,elt.commission_remain);
// println!("Transact at ask rate. Qty={} elt.sell_remain={} elt.royalty_remain={} elt.commission_remain={}",qty,elt.sell_remain,elt.royalty_remain,elt.commission_remain);
let rq2=if !elt.sell_remain.is_zero() { elt.royalty_remain *qty/elt.sell_remain } else { FiNum::zero() };
let cq2=if !elt.sell_remain.is_zero() { elt.commission_remain*qty/elt.sell_remain } else { FiNum::zero() };
royalty_acc+=rq0+rq1;
@@ -732,7 +749,7 @@ impl Market {
self.rng=StdRng::seed_from_u64(seed);
}
fn random_command(&mut self) -> Command {
match self.rng.gen_range(1..3) {
match self.rng.gen_range(1..4) {
1 => 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)), },
@@ -744,7 +761,7 @@ impl Market {
sell_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)),
buy_type: self.rng.gen_range(0..self.assets.len()),
buy_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), },
// 4 => Command::RetractOrder { {*}
4 => if let Some(id)=self.random_order_id() { Command::RetractOrder { order_id:id } } else { Command::None },
_ => Command::Error("This can never happen".to_string()),
}
}
@@ -982,7 +999,7 @@ impl Market {
}
Command::AddFunds{ user_id, asset_id, amt } => {
self.add_trader_balance(*user_id,*asset_id,*amt);
println!("Added {} {} to {}",*amt,self.number_to_asset(*asset_id).name,self.traders[*user_id].name);
// println!("Added {} {} to {}",*amt,self.number_to_asset(*asset_id).name,self.traders[*user_id].name);
Result::FundsRemaining(self.get_trader_balance(*user_id,*asset_id))
}
Command::SubFunds { user_id,asset_id,amt } => {
@@ -1003,7 +1020,8 @@ impl Market {
self.retract_order(*order_id)
}
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)
Result::Error(format!("ExecuteBatch not Implemented."))
}
Command::Error(str) => Result::Error(format!("Command Error")),
Command::NOP(str) => Result::Ok,
@@ -1072,7 +1090,7 @@ fn tokens_to_command(m: &Market, logged_in: usize, tokens: Vec<&str>,line: &str)
let order_id:usize=p_order_id.parse().unwrap();
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 order_type=trader.order_finder.get(&order_id);
let order_type=m.order_finder.get(&order_id);
println!("Order_type {:?}",order_type);
let order_queue=m.orders.get(order_type.expect("Retrieving Order Queue"));
Command::RetractOrder { order_id: order_id }
@@ -1164,13 +1182,15 @@ fn interactive(m: &mut Market, mut out: Option<File>) {
let qty:u32=qty.parse().unwrap();
for i in 0..qty {
let cmd=m.random_command();
println!("RandomCommand #{}: {}",1+i,cmd.serialize());
// println!("RandomCommand #{}: {}",1+i,cmd.serialize());
if let Some(ref mut f)=out {
let ser=cmd.serialize();
if let Err(e)=writeln!(f,"{}",ser) { eprintln!("An error occurred while writing {}",e); }
} else { println!("{}",cmd.serialize()); }
} else {
// println!("{}",cmd.serialize());
}
let res=m.execute(&cmd);
println!("Result: {}",res.describe());
// println!("Result: {}",res.describe());
}
Command::None
},
@@ -1243,7 +1263,7 @@ fn main() {
}
if mode_count==0 { mode=Mode::Interactive; mode_count+=1; }
if mode_count!=1 { println!("You may only select one mode to run in."); return; }
let mut m=Market::new(); // USD type is 1, EUR type is 2, BTC type is 10, ETH type is 11, zKN6FBdD SOL type is 12
let mut m=Market::new(); // USD type is 1, EUR type is 2, BTC type is 10, ETH type is 11, SOL type is 12
if options.contains_key("replay") { m.replay_file(options.get("replay").unwrap()); }
match mode {
Mode::Interactive => {