Path Finding and arbitrage detection works. Need to print out when detecting arbitrage.
This commit is contained in:
@@ -24,6 +24,9 @@ impl FiNum {
|
||||
pub fn one() -> Self {
|
||||
FiNum(1u64<<32)
|
||||
}
|
||||
pub fn infinity() -> Self {
|
||||
FiNum(u64::MAX)
|
||||
}
|
||||
pub fn is_tiny(self) -> bool {
|
||||
self.0>0u64 && self.0<=1u64
|
||||
}
|
||||
|
||||
82
src/main.rs
82
src/main.rs
@@ -36,6 +36,13 @@
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Thoughts on cheapest-path algorithm:
|
||||
// Create a square matrix of costs from each asset to each asset. Some of the entries will be infinity. The goal is to lower the entries.
|
||||
// In each cell, store not just the cost, but the path and path capacity.
|
||||
// Starting with the source asset, see if visiting each other asset lowers the cost to get there. If it does, replace that asset's cost with the new cost and path.
|
||||
//
|
||||
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
#![allow(unused_variables)]
|
||||
@@ -48,6 +55,7 @@ use std::io::{self, BufRead, Write};
|
||||
use std::env;
|
||||
use std::collections::HashMap;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::min;
|
||||
use rand::prelude::*;
|
||||
use rand::rngs::StdRng;
|
||||
use std::time::Instant;
|
||||
@@ -728,7 +736,68 @@ impl Market {
|
||||
commission_acc,self.number_to_name(sell_type),self.traders[owner].name));
|
||||
Result::PlacedOrder(id,log)
|
||||
}
|
||||
fn path_cost(&self, src: usize, dest: usize, depth_left: usize) -> TradePath {
|
||||
let mut cheapest=vec![TradePath::new();self.assets.len()];
|
||||
cheapest[src].cost=FiNum::new_i32(1);
|
||||
cheapest[src].path[0]=src;
|
||||
cheapest[src].len=1;
|
||||
for i in 0..6 {
|
||||
let mut progress=false;
|
||||
for ass0 in 0..self.assets.len() {
|
||||
for ass1 in 0..self.assets.len() {
|
||||
if true || ass0!=ass1 {
|
||||
if let Some(topq)=self.orders.get(&(ass1,ass0)) {
|
||||
if let Some(top)=topq.peekn() {
|
||||
println!("There is a direct path from {} to {} with a cost of {} {}",
|
||||
self.number_to_name(ass0),self.number_to_name(ass1),top.buy_qty/top.sell_qty,self.number_to_name(ass1));
|
||||
let candidate=cheapest[ass0].cost*top.buy_qty/top.sell_qty;
|
||||
if candidate<cheapest[ass1].cost {
|
||||
// Extend cheapest[ass1]
|
||||
println!("Extending Length {} {} because {} < {}",cheapest[ass0].len,self.number_to_name(ass1),candidate,cheapest[ass1].cost);
|
||||
cheapest[ass1]=cheapest[ass0];
|
||||
let ext=&mut cheapest[ass1];
|
||||
let arbitrage=ext.path.contains(&ass1);
|
||||
ext.path[ext.len]=ass1;
|
||||
ext.len+=1;
|
||||
ext.cost=candidate;
|
||||
ext.cap=min(ext.cap,ext.cost*top.sell_remain);
|
||||
progress=true;
|
||||
if arbitrage {
|
||||
|
||||
return ext.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !progress { println!("Definitely found the cheapest path."); break; }
|
||||
}
|
||||
for ass in 0..self.assets.len() { println!("Cheapest path from {} to {} is {}",self.number_to_name(src),self.number_to_name(ass),cheapest[ass].cost); }
|
||||
cheapest[dest].clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy,Clone)]
|
||||
struct TradePath {
|
||||
cost: FiNum,
|
||||
path: [ usize; 600],
|
||||
len: usize,
|
||||
cap: FiNum,
|
||||
arbitrage: bool,
|
||||
}
|
||||
|
||||
impl TradePath {
|
||||
fn new() -> Self { TradePath {
|
||||
cost: FiNum::infinity(),
|
||||
path: [0; 600],
|
||||
len: 0,
|
||||
cap: FiNum::infinity(),
|
||||
arbitrage: false,
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
impl PartialOrd for Order {
|
||||
fn partial_cmp(&self, other:&Self) -> Option<Ordering> {
|
||||
@@ -764,6 +833,9 @@ impl OrderQueue {
|
||||
fn peek(&mut self) -> &mut Order {
|
||||
self.v.first_mut().unwrap()
|
||||
}
|
||||
fn peekn(&self) -> Option<&Order> {
|
||||
self.v.first()
|
||||
}
|
||||
fn empty(&self) -> bool {
|
||||
self.v.len()==0
|
||||
}
|
||||
@@ -1252,6 +1324,16 @@ fn interactive(m: &mut Market, mut out: Option<File>) {
|
||||
let cmd:Command=match tokens.as_slice() {
|
||||
["dump"] => { m.dump(); Command::None },
|
||||
["sanity"] => { m.sanity_check(); Command::None },
|
||||
["path",src,dest] => {
|
||||
let cur0=*m.name_to_number(src).unwrap();
|
||||
let cur1=*m.name_to_number(dest).unwrap();
|
||||
let path=m.path_cost(cur0,cur1,6);
|
||||
let mut str=format!("Cost: {} Cap: {}",path.cost,path.cap);
|
||||
if path.len>0 { str=format!("{} {}",str,m.number_to_name(path.path[0])) }
|
||||
for i in 1..path.len { str=format!("{}->{}",str,m.number_to_name(path.path[i])) }
|
||||
println!("{}",str);
|
||||
Command::None
|
||||
},
|
||||
["randomorder"] => { println!("Random OrderID: {:?}",m.random_order_id()); Command::None }
|
||||
["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) }
|
||||
|
||||
Reference in New Issue
Block a user