Added and tested Shadowing at the OrderQueue level
This commit is contained in:
104
src/main.rs
104
src/main.rs
@@ -54,6 +54,7 @@ use std::path::Path;
|
||||
use std::io::{self, BufRead, Write};
|
||||
use std::env;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::min;
|
||||
use rand::prelude::*;
|
||||
@@ -370,7 +371,7 @@ impl Dumpable for usize {
|
||||
|
||||
impl Dumpable for Order {
|
||||
fn dump(&self) {
|
||||
println!("Giving {}/{} to get {}",self.sell_remain,self.sell_qty,self.buy_qty);
|
||||
println!("Giving {}/{} ({} each) to get {}",self.sell_remain,self.sell_qty,self.buy_qty/self.sell_qty,self.buy_qty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +383,7 @@ struct Market {
|
||||
traders: Vec<Trader>,
|
||||
trader_name2num: HashMap<String,usize>,
|
||||
orders: HashMap<(usize,usize),OrderQueue>,
|
||||
shadows: HashSet<(usize,usize)>,
|
||||
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>,
|
||||
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
|
||||
@@ -399,6 +401,7 @@ impl Market {
|
||||
traders: Vec::new(),
|
||||
trader_name2num: HashMap::new(),
|
||||
orders: HashMap::new(),
|
||||
shadows: HashSet::new(),
|
||||
royalties: HashMap::new(),
|
||||
royalty_rate: HashMap::new(),
|
||||
order_finder: HashMap::new(),
|
||||
@@ -573,6 +576,8 @@ impl Market {
|
||||
let ap0=(asset_type0,asset_type1);
|
||||
let ap1=(asset_type1,asset_type0);
|
||||
let [bids0,bids1]=self.orders.get_many_mut([&ap0, &ap1]).unwrap(); // There's a workaround for this where you remove and reinsert the keys.
|
||||
let bids0p=bids0.peek();
|
||||
let bids1p=bids1.peek();
|
||||
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 {
|
||||
@@ -763,7 +768,7 @@ impl Market {
|
||||
ext.cap=min(ext.cap,ext.cost*top.sell_remain);
|
||||
progress=true;
|
||||
if arbitrage {
|
||||
|
||||
ext.arbitrage=true;
|
||||
return ext.clone();
|
||||
}
|
||||
}
|
||||
@@ -824,7 +829,7 @@ struct OrderQueue {
|
||||
v: Vec<Order>,
|
||||
shadowing: bool,
|
||||
shadow: Option<Order>,
|
||||
next: Vec<usize>,
|
||||
next: Vec<usize>, // A priority queue
|
||||
order_finder: HashMap<usize,usize>, // Maps OrderIDs to locations in v
|
||||
}
|
||||
|
||||
@@ -839,20 +844,62 @@ impl OrderQueue {
|
||||
order_finder:HashMap::new(),
|
||||
}
|
||||
}
|
||||
fn start_shadow(&mut self) {
|
||||
assert!(self.shadowing==false);
|
||||
self.shadowing=true;
|
||||
self.shadow=if self.v.len()>0 { Some(self.v[0].clone()) } else { None }
|
||||
fn assure_shadowing(&mut self) {
|
||||
if !self.shadowing {
|
||||
assert!(self.next.len()==0);
|
||||
self.shadowing=true;
|
||||
if self.v.len()>0 { self.shadow=Some(self.v[0].clone()); }
|
||||
else { self.shadow=None; }
|
||||
self.queue_shadow(0);
|
||||
}
|
||||
}
|
||||
fn stop_shadowing(&mut self) {
|
||||
if self.shadowing {
|
||||
self.next.clear();
|
||||
self.shadowing=false;
|
||||
self.shadow=None;
|
||||
self.next=Vec::new();
|
||||
}
|
||||
}
|
||||
fn queue_shadow(&mut self, parent: usize) {
|
||||
if parent*2+1<self.v.len() { self.next.push(parent*2+1); self.bubble_up_next(self.next.len()-1); }
|
||||
if parent*2+2<self.v.len() { self.next.push(parent*2+2); self.bubble_up_next(self.next.len()-1); }
|
||||
}
|
||||
fn peek(&mut self) -> &mut Order {
|
||||
self.v.first_mut().unwrap()
|
||||
if !self.shadowing { self.v.first_mut().unwrap() }
|
||||
else { self.shadow.as_mut().expect("Shadowing mismatch") }
|
||||
}
|
||||
fn peekn(&self) -> Option<&Order> {
|
||||
self.v.first()
|
||||
match &self.shadow {
|
||||
Some(order) => Some(order),
|
||||
None => { self.v.first() }
|
||||
}
|
||||
}
|
||||
fn empty(&self) -> bool {
|
||||
self.v.len()==0
|
||||
}
|
||||
fn pop(&mut self) -> Option<Order> {
|
||||
if !self.shadowing { return self.remove(0); }
|
||||
let rval=self.shadow.clone();
|
||||
if self.next.len()==0 { self.shadow=None; }
|
||||
else {
|
||||
self.shadow=Some(self.v[self.next[0]].clone());
|
||||
self.queue_shadow(self.next[0]);
|
||||
if self.next.len()>1 { self.next[0]=self.next.pop().unwrap(); }
|
||||
else { self.next.pop(); }
|
||||
self.trickle_down_next(0);
|
||||
}
|
||||
rval
|
||||
}
|
||||
fn bubble_up_next(&mut self, pos: usize) {
|
||||
if pos>0 {
|
||||
let parent=(pos-1)/2;
|
||||
if self.v[self.next[parent]]<self.v[self.next[pos]] {
|
||||
self.next.swap(parent,pos);
|
||||
self.bubble_up_next(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn bubble_up(&mut self, pos: usize) {
|
||||
if pos>0 {
|
||||
let parent=(pos-1)/2;
|
||||
@@ -882,16 +929,30 @@ impl OrderQueue {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn trickle_down_next(&mut self, pos: usize) {
|
||||
let mut pivot=pos;
|
||||
let child0=pos*2+1;
|
||||
let child1=pos*2+2;
|
||||
if child0<self.next.len() {
|
||||
if self.v[self.next[pos]]<self.v[self.next[child0]] { pivot=child0; }
|
||||
if child1<self.next.len() {
|
||||
if self.v[self.next[pivot]]<self.v[self.next[child1]] { pivot=child1; }
|
||||
}
|
||||
if pivot!=pos {
|
||||
self.next.swap(pivot,pos);
|
||||
self.trickle_down_next(pivot);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn insert(&mut self, item: Order) {
|
||||
assert!(!self.shadowing);
|
||||
let id=item.order_id;
|
||||
self.v.push(item);
|
||||
self.order_finder.insert(id,self.v.len()-1);
|
||||
self.bubble_up(self.v.len()-1);
|
||||
}
|
||||
fn pop(&mut self) -> Option<Order> {
|
||||
self.remove(0)
|
||||
}
|
||||
fn remove(&mut self, pos: usize) -> Option<Order> {
|
||||
assert!(!self.shadowing);
|
||||
if self.v.len()<=pos { None }
|
||||
else {
|
||||
let end=self.v.len()-1;
|
||||
@@ -906,6 +967,7 @@ impl OrderQueue {
|
||||
for index in 0..self.v.len() {
|
||||
self.v[index].dump();
|
||||
}
|
||||
if self.shadowing { for index in 0..self.next.len() { println!(" Shadow {}",self.next[index]); } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1382,6 +1444,24 @@ fn interactive(m: &mut Market, mut out: Option<File>) {
|
||||
println!("Seeded RNG with {}",seed);
|
||||
Command::None
|
||||
}
|
||||
["testshadow",src,dst] => {
|
||||
if let Some(cur0)=m.name_to_number(src) {
|
||||
if let Some(cur1)=m.name_to_number(dst) {
|
||||
println!("Currencies are {} and {}",cur0,cur1);
|
||||
if let Some(q)=m.orders.get_mut(&(*cur0,*cur1)) {
|
||||
println!("Dumping queue");
|
||||
q.dump();
|
||||
println!("Dumping shadow");
|
||||
q.assure_shadowing();
|
||||
while let Some(ord)=q.pop() {
|
||||
ord.dump();
|
||||
}
|
||||
q.stop_shadowing();
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::None
|
||||
}
|
||||
["randomcommands"|"rc", qty] => {
|
||||
let qty:u32=qty.parse().unwrap();
|
||||
let start = Instant::now();
|
||||
|
||||
Reference in New Issue
Block a user