2024-05-30 22:22:02 -04:00
//
// When inserting a new Order into the royalties tree, we must make sure the existing
// royalties don't get shared with that new node. To do this, we must "shave" down
// the tree, pushing royalties from the root down to all nodes to the left of the
// new node.
//
// Case to think about:
// Selling 140000 USD to buy 2 BTC. Weight is ===140k USD
// Selling 50000 GBP to buy 1 BTC. Weight is === 50k GBP
//
2024-05-21 17:55:05 -04:00
#![ allow(unsafe_code) ]
2024-05-30 22:22:02 -04:00
#![ allow(unused_variables) ]
#![ allow(dead_code) ]
2024-06-20 16:22:08 -04:00
use std ::io ::{ self , BufRead } ;
2024-05-26 08:19:55 -04:00
use std ::env ;
2024-05-09 09:52:52 -10:00
use std ::collections ::HashMap ;
use std ::cmp ::Ordering ;
2024-05-26 08:19:55 -04:00
use std ::rc ::Rc ;
2024-05-26 20:37:08 -04:00
use std ::cell ::RefCell ;
2024-05-19 09:47:40 -04:00
use rand ::prelude ::* ;
use rand ::rngs ::StdRng ;
2024-05-18 14:28:12 -04:00
use finum ::FiNum ;
2024-05-09 09:52:52 -10:00
2024-05-15 06:59:09 -04:00
#[ derive(Debug, Clone) ]
struct Trader {
name : String ,
2024-06-20 16:22:08 -04:00
password : String , // hash(name..salt..password)
2024-05-30 22:22:02 -04:00
id : usize ,
balances : HashMap < usize , FiNum > , // Maps Currency to Amount
2024-05-15 06:59:09 -04:00
}
2024-06-18 19:19:25 -04:00
#[ derive(Clone) ]
2024-06-18 16:18:01 -04:00
struct Asset {
name : String ,
royalty0_rate : FiNum , // Traders get this when entered
royalty1_rate : FiNum , // Traders get this when executed
commission0_rate : FiNum , // House gets this when entered
commission1_rate : FiNum , // House gets this when executed
}
impl Asset {
fn new ( name : & str ) -> Self {
Asset {
name : String ::from ( name ) ,
royalty0_rate :FiNum ::zero ( ) ,
royalty1_rate :FiNum ::zero ( ) ,
commission0_rate :FiNum ::zero ( ) ,
commission1_rate :FiNum ::zero ( ) ,
}
}
}
2024-06-18 19:19:25 -04:00
2024-05-15 06:59:09 -04:00
impl Trader {
2024-05-30 22:22:02 -04:00
fn new ( name :& str , id :usize ) -> Self {
2024-05-15 06:59:09 -04:00
Trader {
2024-05-18 23:59:58 -04:00
name : String ::from ( name ) ,
2024-06-20 16:22:08 -04:00
password : String ::from ( " " ) ,
2024-05-18 23:59:58 -04:00
id : id ,
balances : HashMap ::new ( )
}
2024-05-15 06:59:09 -04:00
}
2024-05-30 22:22:02 -04:00
fn add_balance ( & mut self , cur :usize , delta :FiNum ) {
2024-05-18 23:59:58 -04:00
self . balances . entry ( cur ) . and_modify ( | ent | * ent + = delta ) . or_insert_with ( | | delta ) ;
}
2024-05-30 22:22:02 -04:00
fn sub_balance ( & mut self , cur :usize , delta :FiNum ) {
2024-05-18 23:59:58 -04:00
self . balances . entry ( cur ) . and_modify ( | ent | * ent - = delta ) ;
}
2024-05-30 22:22:02 -04:00
fn get_balance ( & self , cur :usize ) -> FiNum {
2024-05-18 14:28:12 -04:00
* self . balances . get ( & cur ) . map ( | bal | bal ) . unwrap_or ( & FiNum ::new ( 0 u64 ) )
2024-05-18 23:59:58 -04:00
}
2024-05-15 06:59:09 -04:00
}
2024-05-09 09:52:52 -10:00
#[ derive(Debug, Clone) ]
2024-05-26 08:19:55 -04:00
struct Order {
2024-05-18 14:28:12 -04:00
sell_qty : FiNum ,
sell_remain : FiNum ,
buy_qty : FiNum ,
2024-06-18 19:19:25 -04:00
royalty_remain : FiNum , // Based on royalty1
commission_remain : FiNum , // Based on commission1
2024-05-30 22:22:02 -04:00
owner : usize ,
2024-06-03 19:36:51 -04:00
rt_loc : usize , // Location in the Royalty Tree
2024-05-15 06:59:09 -04:00
}
2024-05-09 09:52:52 -10:00
2024-05-30 22:22:02 -04:00
struct RoyaltyTree {
tree : Vec < Royalty > ,
2024-06-13 17:47:00 -04:00
next_entry : usize ,
2024-06-18 19:19:25 -04:00
spare_change : FiNum , // Waiting to be distributed
2024-05-30 22:22:02 -04:00
}
struct Royalty {
weight : FiNum , // Here and below
2024-06-13 17:47:00 -04:00
lazy : FiNum , // To be distributed to here and to below based on weights
2024-06-09 21:13:07 -04:00
acc : FiNum , // Accumulated here
2024-05-30 22:22:02 -04:00
}
impl Royalty {
2024-06-09 21:13:07 -04:00
fn new ( ) -> Self {
Royalty { weight :FiNum ::zero ( ) , lazy :FiNum ::zero ( ) , acc :FiNum ::zero ( ) }
2024-05-30 22:22:02 -04:00
}
}
impl RoyaltyTree {
2024-06-09 21:13:07 -04:00
fn new ( ) -> Self {
2024-06-20 16:22:08 -04:00
RoyaltyTree { tree :Vec ::new ( ) , next_entry :0 , spare_change :FiNum ::zero ( ) }
2024-06-13 17:47:00 -04:00
}
2024-06-09 21:13:07 -04:00
fn weight_here_below ( & self , index :usize ) -> FiNum {
2024-06-13 17:47:00 -04:00
self . tree [ index ] . weight
}
2024-06-11 17:44:11 -04:00
fn weight_below ( & self , index : usize ) -> FiNum {
2024-06-09 21:13:07 -04:00
if index & 1 = = 0 {
2024-06-13 17:47:00 -04:00
FiNum ::zero ( )
} else {
2024-06-11 17:44:11 -04:00
let w0 = self . weight_here_below ( wt_left ( index ) . unwrap ( ) ) ;
2024-06-13 17:47:00 -04:00
let w1 = self . weight_here_below ( wt_right ( index ) . unwrap ( ) ) ;
w0 + w1
}
}
2024-06-09 21:13:07 -04:00
fn weight_here ( & self , index :usize ) -> FiNum {
if index & 1 = = 0 {
2024-06-13 17:47:00 -04:00
self . weight_here_below ( index )
} else {
2024-06-10 18:39:12 -04:00
let w0 = self . weight_here_below ( index ) ;
let w1 = self . weight_below ( index ) ;
w0 - w1
2024-06-13 17:47:00 -04:00
}
}
2024-06-09 21:13:07 -04:00
fn expand_to ( & mut self , index : usize ) -> & mut Self {
2024-06-14 10:14:33 -04:00
for _ in self . tree . len ( ) ..= index { self . tree . push ( Royalty ::new ( ) ) }
2024-06-13 17:47:00 -04:00
self
2024-06-09 21:13:07 -04:00
}
fn capture0 ( & mut self , index : usize ) -> & mut Self {
2024-06-13 17:47:00 -04:00
if index & 1 = = 0 {
let lazy = self . tree [ index ] . lazy ;
self . tree [ index ] . acc + = lazy ;
self . tree [ index ] . lazy = FiNum ::zero ( ) ;
} else {
let lazy = self . tree [ index ] . lazy ;
2024-06-13 22:51:32 -04:00
let d1 = if lazy > 0. into ( ) { lazy * self . weight_here ( index ) / self . weight_here_below ( index ) } else { FiNum ::zero ( ) } ;
2024-06-13 17:47:00 -04:00
let d02 = lazy - d1 ;
let index_left = wt_left ( index ) . unwrap ( ) ;
let index_right = wt_right ( index ) . unwrap ( ) ;
2024-06-13 22:51:32 -04:00
let d0 = if d02 > 0. into ( ) { d02 * self . weight_here_below ( index_left ) / self . weight_below ( index ) } else { FiNum ::zero ( ) } ;
2024-06-13 17:47:00 -04:00
let d2 = d02 - d0 ;
assert! ( lazy = = d0 + d1 + d2 , " Distributing amounts that don't add up. " ) ;
self . tree [ index_left ] . lazy + = d0 ;
self . tree [ index_right ] . lazy + = d2 ;
self . tree [ index ] . acc + = d1 ;
self . tree [ index ] . lazy = FiNum ::zero ( ) ;
}
self
2024-05-30 22:22:02 -04:00
}
2024-06-10 15:08:18 -04:00
fn get_royalty ( & mut self , index : usize ) -> FiNum {
2024-06-10 01:45:03 -04:00
let mut f = self . forefather ( ) ;
2024-06-13 17:47:00 -04:00
while f ! = index {
self . capture0 ( f ) ;
f = if f > index { wt_left ( f ) . unwrap ( ) } else { wt_right ( f ) . unwrap ( ) }
}
self . capture0 ( f ) ;
self . tree [ index ] . acc
}
2024-06-10 01:45:03 -04:00
fn add_royalty ( & mut self , amount : FiNum ) {
2024-06-20 16:22:08 -04:00
if self . next_entry = = 0 { self . spare_change + = amount }
2024-06-18 19:19:25 -04:00
else {
let ff = self . forefather ( ) ;
if self . weight_here_below ( ff ) . is_zero ( ) { self . spare_change + = amount } else { self . tree [ ff ] . lazy + = amount } ;
}
2024-06-13 17:47:00 -04:00
}
fn add_weight ( & mut self , index : usize , weight : FiNum ) {
2024-06-13 22:51:32 -04:00
if self . tree . len ( ) > 0 {
2024-06-13 17:47:00 -04:00
let mut ff0 = self . forefather ( ) ;
2024-06-13 22:51:32 -04:00
let ff1 = wt_forefather ( index ) ;
let w = self . tree [ ff0 ] . weight ;
self . expand_to ( ff1 * 2 ) ;
while ff0 < ff1 {
ff0 = wt_parent ( ff0 ) ;
self . tree [ ff0 ] . weight = w ;
}
2024-06-13 17:47:00 -04:00
}
2024-06-13 22:51:32 -04:00
else { self . expand_to ( wt_forefather ( index ) * 2 ) ; }
2024-06-13 17:47:00 -04:00
self . get_royalty ( index ) ; // Just for the side effect of capturing everything to this point
let mut index = index ;
2024-06-13 22:51:32 -04:00
let ff = self . forefather ( ) ;
2024-06-13 17:47:00 -04:00
while index ! = ff {
self . tree [ index ] . weight + = weight ;
index = wt_parent ( index ) ;
2024-06-10 18:39:12 -04:00
}
2024-06-13 17:47:00 -04:00
self . tree [ index ] . weight + = weight ;
}
2024-06-10 01:45:03 -04:00
fn forefather ( & self ) -> usize {
wt_forefather ( self . tree . len ( ) - 1 )
2024-06-13 17:47:00 -04:00
}
2024-06-10 15:08:18 -04:00
fn dump ( & mut self ) {
2024-06-03 19:36:51 -04:00
for index in 0 .. self . tree . len ( ) {
2024-06-13 17:47:00 -04:00
let roy = self . get_royalty ( index ) ;
println! ( " Index {} Weight {} Lazy {} Acc {} Royalty {} " , index , self . tree [ index ] . weight , self . tree [ index ] . lazy , self . tree [ index ] . acc , roy ) ;
}
}
2024-05-30 22:22:02 -04:00
}
2024-06-13 17:47:00 -04:00
2024-05-30 22:22:02 -04:00
2024-05-09 09:52:52 -10:00
trait Dumpable {
fn dump ( & self ) ;
}
2024-05-30 22:22:02 -04:00
impl Dumpable for usize {
2024-05-20 11:00:45 -04:00
fn dump ( & self ) {
println! ( " Dump Integer: {} " , self ) ;
}
}
2024-05-26 08:19:55 -04:00
impl Dumpable for Rc < RefCell < Order > > {
fn dump ( & self ) {
}
}
impl Dumpable for Order {
2024-05-09 09:52:52 -10:00
fn dump ( & self ) {
2024-05-18 14:28:12 -04:00
println! ( " Giving {} / {} to get {} " , self . sell_remain , self . sell_qty , self . buy_qty ) ;
2024-05-09 09:52:52 -10:00
}
}
2024-05-26 08:19:55 -04:00
2024-05-09 09:52:52 -10:00
struct Market {
2024-05-30 22:22:02 -04:00
asset_name2num : HashMap < String , usize > ,
2024-06-18 16:18:01 -04:00
assets : Vec < Asset > ,
2024-05-30 22:22:02 -04:00
money_supply : HashMap < usize , FiNum > ,
2024-05-15 06:59:09 -04:00
traders : Vec < Trader > ,
2024-05-30 22:22:02 -04:00
trader_name2num : HashMap < String , usize > ,
orders : HashMap < ( usize , usize ) , PQueue < Rc < RefCell < Order > > > > ,
royalties : HashMap < usize , RoyaltyTree > , // Active orders that are accepting asset X. They receive royalties when someone makes an order to sell X
2024-06-18 16:18:01 -04:00
royalty_rate : HashMap < usize , FiNum > ,
2024-05-15 06:59:09 -04:00
}
2024-05-09 09:52:52 -10:00
impl Market {
fn new ( ) -> Self {
2024-05-30 22:22:02 -04:00
let mut rval = Market {
2024-05-09 09:52:52 -10:00
asset_name2num : HashMap ::new ( ) ,
2024-06-18 16:18:01 -04:00
assets : Vec ::new ( ) ,
2024-05-16 17:11:09 -04:00
money_supply : HashMap ::new ( ) ,
2024-05-18 23:59:58 -04:00
traders : Vec ::new ( ) ,
2024-05-16 15:50:37 -04:00
trader_name2num : HashMap ::new ( ) ,
2024-06-18 16:18:01 -04:00
orders : HashMap ::new ( ) ,
royalties : HashMap ::new ( ) ,
royalty_rate : HashMap ::new ( ) ,
2024-05-30 22:22:02 -04:00
} ;
2024-06-18 19:19:25 -04:00
rval . register_trader ( " *HOUSE* " ) ;
2024-06-13 17:47:00 -04:00
rval
2024-05-09 09:52:52 -10:00
}
2024-05-16 17:11:09 -04:00
fn sanity_check ( & self ) {
println! ( " Sanity Checking Market... " ) ;
for ( cur , amt ) in self . money_supply . iter ( ) {
2024-05-18 14:28:12 -04:00
println! ( " Money Supply {} : {} " , self . number_to_name ( * cur ) , * amt ) ;
2024-05-26 08:19:55 -04:00
let mut acc_orders = FiNum ::new ( 0 ) ;
for ( ac , pq ) in & self . orders { if ac . 0 = = * cur {
2024-05-26 20:37:08 -04:00
for off in & * pq . v { acc_orders + = off . borrow ( ) . sell_remain ; }
2024-05-16 17:11:09 -04:00
} }
2024-05-18 14:28:12 -04:00
let mut acc_traders = FiNum ::new ( 0 ) ;
2024-05-16 17:11:09 -04:00
for t in & self . traders { acc_traders + = t . get_balance ( * cur ) ; }
2024-05-26 08:19:55 -04:00
let acc = acc_orders + acc_traders ;
println! ( " {} : Orders {} Traders {} Total {} Should Be {} " , self . number_to_name ( * cur ) , acc_orders , acc_traders , acc , * amt ) ;
2024-05-16 17:11:09 -04:00
}
}
2024-05-30 22:22:02 -04:00
fn register_trader ( & mut self , name :& str ) -> usize { // Add error checking for inserting a trader twice
let rval = self . traders . len ( ) ;
self . trader_name2num . insert ( String ::from ( name ) , self . traders . len ( ) ) ;
2024-05-18 23:59:58 -04:00
self . traders . push ( Trader ::new ( name , rval ) ) ;
2024-05-16 17:11:09 -04:00
rval
2024-05-18 23:59:58 -04:00
}
2024-05-16 17:11:09 -04:00
// These are the only ways to get money into or out of the market.
2024-05-30 22:22:02 -04:00
fn add_trader_balance ( & mut self , who :usize , cur :usize , delta : FiNum ) {
2024-05-16 15:50:37 -04:00
self . traders [ who as usize ] . add_balance ( cur , delta ) ;
2024-05-16 17:11:09 -04:00
* self . money_supply . get_mut ( & cur ) . unwrap ( ) + = delta ;
2024-05-16 15:50:37 -04:00
}
2024-05-30 22:22:02 -04:00
fn sub_trader_balance ( & mut self , who :usize , cur :usize , delta : FiNum ) {
2024-05-16 15:50:37 -04:00
self . traders [ who as usize ] . sub_balance ( cur , delta ) ;
2024-05-16 17:11:09 -04:00
* self . money_supply . get_mut ( & cur ) . unwrap ( ) - = delta ;
2024-05-16 15:50:37 -04:00
}
2024-06-23 18:50:48 -04:00
fn register_asset ( & mut self , name :& str ) -> Option < usize > {
if self . asset_name2num . contains_key ( name ) { return None }
2024-06-18 16:18:01 -04:00
self . assets . push ( Asset ::new ( name ) ) ;
self . asset_name2num . insert ( String ::from ( name ) , self . assets . len ( ) - 1 ) ;
self . money_supply . insert ( self . assets . len ( ) - 1 , FiNum ::new ( 0 ) ) ;
2024-06-23 18:50:48 -04:00
let rval = self . assets . len ( ) - 1 ;
Some ( rval )
2024-05-09 09:52:52 -10:00
}
2024-06-18 19:19:25 -04:00
fn number_to_asset ( & self , n : usize ) -> Asset {
self . assets [ n ] . clone ( )
}
fn number_to_name ( & self , n : usize ) -> String {
self . assets [ n ] . name . clone ( )
}
2024-06-23 18:50:48 -04:00
fn name_to_number ( & self , name :& str ) -> Option < & usize > {
self . asset_name2num . get ( name )
2024-05-09 09:52:52 -10:00
}
fn dump ( & self ) {
println! ( " Dumping Market: " ) ;
2024-05-16 15:50:37 -04:00
for t in & self . traders {
println! ( " Trader {} : {} " , t . id , t . name ) ;
for ( cur , bal ) in t . balances . iter ( ) {
2024-05-18 14:28:12 -04:00
println! ( " {} : {} " , self . number_to_name ( * cur ) , * bal )
2024-05-16 15:50:37 -04:00
}
}
2024-05-26 08:19:55 -04:00
for ( ap , pq ) in & self . orders {
println! ( " Orders selling {} to buy {} : " , self . number_to_name ( ap . 0 ) , self . number_to_name ( ap . 1 ) ) ;
2024-05-19 09:47:40 -04:00
let mut sorted = pq . v . clone ( ) ;
2024-05-26 20:37:08 -04:00
sorted . sort_by ( | a , b | { let a = a . borrow ( ) ; let b = b . borrow ( ) ; ( a . sell_qty / a . buy_qty ) . cmp ( & ( b . sell_qty / b . buy_qty ) ) } ) ;
2024-05-19 09:47:40 -04:00
for off in sorted . iter ( ) {
2024-05-30 22:22:02 -04:00
let off = off . borrow ( ) ;
2024-05-19 09:47:40 -04:00
println! ( " {} @ {} ( {} ) " ,
2024-05-20 11:00:45 -04:00
off . sell_remain , // off.buy_qty*off.sell_remain/off.sell_qty,
off . buy_qty / off . sell_qty ,
2024-05-19 09:47:40 -04:00
self . traders [ off . owner as usize ] . name ) ;
}
2024-05-20 11:00:45 -04:00
pq . dump ( ) ;
2024-05-09 09:52:52 -10:00
}
}
2024-05-30 22:22:02 -04:00
fn make_order ( & mut self , owner :usize , sell_type :usize , buy_type :usize , sell_qty_initial :FiNum , buy_qty_initial :FiNum ) -> bool // Dollars, Bitcoin, 64000, 1
2024-05-18 23:59:58 -04:00
{
2024-06-19 18:38:46 -04:00
let initial_balance = self . traders [ owner ] . get_balance ( sell_type ) ;
2024-06-18 19:19:25 -04:00
let asset = self . number_to_asset ( sell_type ) ;
let mut royalty0_qty = asset . royalty0_rate * sell_qty_initial ;
let mut royalty1_qty = asset . royalty1_rate * sell_qty_initial ;
let mut commission0_qty = asset . commission0_rate * sell_qty_initial ;
let mut commission1_qty = asset . commission1_rate * sell_qty_initial ;
2024-06-20 16:22:08 -04:00
let sell_qty_plus = sell_qty_initial + royalty0_qty + royalty1_qty + commission0_qty + commission1_qty ; // This is the maximum amount we are going to sell
let sell_qty = sell_qty_initial ;
2024-06-19 18:38:46 -04:00
if initial_balance < sell_qty_plus { return false ; }
let mut buy_qty = buy_qty_initial ;
let ap = ( buy_type , sell_type ) ;
let mut royalty_acc = FiNum ::zero ( ) ;
let mut commission_acc = FiNum ::zero ( ) ;
2024-05-26 08:19:55 -04:00
while buy_qty > FiNum ::new ( 0 ) & & self . orders . contains_key ( & ap ) & & self . orders . get ( & ap ) . unwrap ( ) . v . len ( ) > 0 {
2024-05-26 20:37:08 -04:00
let mut elt = ( * ( self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow ( ) ) ) . clone ( ) ;
2024-06-19 18:38:46 -04:00
if sell_qty / buy_qty_initial > = elt . buy_qty / elt . sell_qty { // Transact at ask_rate
2024-05-18 23:59:58 -04:00
let qty = std ::cmp ::min ( elt . sell_remain , buy_qty ) ;
elt . sell_remain - = qty ;
buy_qty - = qty ;
2024-06-18 19:19:25 -04:00
let pay_qty = qty * elt . buy_qty / elt . sell_qty ;
2024-06-19 18:38:46 -04:00
self . traders [ owner ] . sub_balance ( sell_type , pay_qty ) ;
self . traders [ owner ] . add_balance ( buy_type , qty ) ;
self . traders [ elt . owner ] . add_balance ( sell_type , pay_qty ) ;
let rq0 = royalty0_qty * pay_qty / sell_qty_initial ;
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 ;
2024-06-20 16:22:08 -04:00
let rq2 = elt . royalty_remain * qty / elt . sell_remain ;
let cq2 = elt . commission_remain * qty / elt . sell_remain ;
2024-06-19 18:38:46 -04:00
royalty_acc + = rq0 + rq1 ;
commission_acc + = cq0 + cq1 ;
2024-06-20 16:22:08 -04:00
royalty0_qty - = rq0 ;
royalty1_qty - = rq1 ;
commission0_qty - = cq0 ;
commission1_qty - = cq1 ;
2024-06-19 18:38:46 -04:00
self . royalties . entry ( sell_type ) . or_insert ( RoyaltyTree ::new ( ) ) . add_royalty ( rq0 + rq1 ) ;
2024-06-20 16:22:08 -04:00
self . royalties . entry ( buy_type ) . or_insert ( RoyaltyTree ::new ( ) ) . add_royalty ( rq2 ) ;
2024-06-19 18:38:46 -04:00
self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow_mut ( ) . royalty_remain - = rq2 ;
self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow_mut ( ) . commission_remain - = cq2 ;
2024-06-20 16:22:08 -04:00
self . traders [ 0 ] . add_balance ( buy_type , cq2 ) ;
2024-06-19 18:38:46 -04:00
self . royalties . entry ( buy_type ) . or_insert ( RoyaltyTree ::new ( ) ) . add_royalty ( rq2 ) ;
if elt . sell_remain = = 0. into ( ) { // deal with pennies stored in royalty_remain and commission_remain
2024-06-20 16:22:08 -04:00
self . traders [ 0 ] . add_balance ( buy_type , self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow_mut ( ) . commission_remain ) ;
self . royalties . entry ( buy_type ) . or_insert ( RoyaltyTree ::new ( ) ) . add_royalty ( self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow_mut ( ) . royalty_remain ) ;
2024-06-19 18:38:46 -04:00
self . orders . get_mut ( & ap ) . unwrap ( ) . pop ( ) ;
} else {
self . orders . get ( & ap ) . unwrap ( ) . v [ 0 ] . borrow_mut ( ) . sell_remain - = qty ;
}
2024-05-19 11:24:59 -04:00
} else { break ; }
2024-05-18 23:59:58 -04:00
}
if buy_qty > 0. into ( ) {
2024-05-09 09:52:52 -10:00
let ap = ( sell_type , buy_type ) ;
2024-05-26 08:19:55 -04:00
if let None = self . orders . get_mut ( & ap ) { self . orders . insert ( ap , PQueue ::new ( ) ) ; }
let bids = self . orders . get_mut ( & ap ) . unwrap ( ) ;
2024-06-19 18:38:46 -04:00
let sell_qty_remain = sell_qty * buy_qty / buy_qty_initial ;
2024-05-19 11:24:59 -04:00
if sell_qty_remain > 0. into ( ) {
2024-06-23 18:50:48 -04:00
self . royalties . entry ( sell_type ) . or_insert ( RoyaltyTree ::new ( ) ) . add_royalty ( royalty0_qty ) ;
2024-06-18 16:18:01 -04:00
let rt = self . royalties . entry ( buy_type ) . or_insert ( RoyaltyTree ::new ( ) ) ;
rt . add_weight ( rt . next_entry , buy_qty ) ; // Weight should really be the quantity you would be able to immediately transact rather than how much you wish for.
2024-05-30 22:22:02 -04:00
let neworder = Rc ::new ( RefCell ::new (
2024-06-23 18:50:48 -04:00
Order { owner :owner , sell_qty :sell_qty_remain , sell_remain :sell_qty_remain , buy_qty :buy_qty , rt_loc : rt . next_entry , royalty_remain :royalty1_qty , commission_remain :commission1_qty } ) ) ;
2024-06-18 16:18:01 -04:00
rt . next_entry + = 1 ;
2024-05-26 20:37:08 -04:00
bids . insert ( neworder ) ;
2024-06-19 18:38:46 -04:00
self . traders [ owner ] . sub_balance ( sell_type , sell_qty_remain ) ;
2024-06-23 18:50:48 -04:00
self . traders [ 0 ] . add_balance ( sell_type , commission0_qty ) ;
2024-05-19 11:24:59 -04:00
}
2024-05-18 23:59:58 -04:00
}
2024-06-23 18:50:48 -04:00
self . traders [ 0 ] . add_balance ( sell_type , commission_acc ) ;
2024-06-19 18:38:46 -04:00
self . traders [ owner ] . sub_balance ( sell_type , royalty_acc + commission_acc ) ;
2024-05-18 23:59:58 -04:00
true
2024-05-13 12:03:03 -04:00
}
}
2024-05-09 09:52:52 -10:00
2024-05-26 08:19:55 -04:00
impl PartialOrd for Order {
2024-05-09 09:52:52 -10:00
fn partial_cmp ( & self , other :& Self ) -> Option < Ordering > {
2024-05-09 12:08:26 -10:00
let ord0 = self . sell_qty / self . buy_qty ;
2024-05-20 11:00:45 -04:00
let ord1 = other . sell_qty / other . buy_qty ;
2024-05-09 09:52:52 -10:00
if ord0 < ord1 { Some ( Ordering ::Less ) }
else if ord0 > ord1 { Some ( Ordering ::Greater ) }
else { Some ( Ordering ::Equal ) }
}
}
2024-05-26 08:19:55 -04:00
impl PartialEq for Order {
2024-05-09 09:52:52 -10:00
fn eq ( & self , other :& Self ) -> bool {
2024-05-13 12:03:03 -04:00
let ord0 = self . sell_qty / self . buy_qty ;
let ord1 = other . sell_qty / other . buy_qty ;
2024-05-09 09:52:52 -10:00
ord0 = = ord1
}
}
2024-05-09 12:08:26 -10:00
2024-05-09 09:52:52 -10:00
struct PQueue < T : Dumpable > {
v : Vec < T > ,
}
impl < T : Dumpable + std ::cmp ::PartialOrd + std ::fmt ::Debug > PQueue < T > {
fn new ( ) ->Self {
PQueue {
v : Vec ::new ( )
}
}
fn peek ( & self ) -> & T {
& self . v [ 0 ]
}
fn bubble_up ( & mut self , pos : usize ) {
if pos > 0 {
let parent = ( pos - 1 ) / 2 ;
2024-05-20 11:00:45 -04:00
if self . v [ parent ] < self . v [ pos ] {
2024-05-09 09:52:52 -10:00
self . v . swap ( parent , pos ) ;
self . bubble_up ( parent ) ;
}
}
}
fn trickle_down ( & mut self , pos : usize ) {
let mut pivot = pos ;
let child0 = pos * 2 + 1 ;
let child1 = pos * 2 + 2 ;
if child0 < self . v . len ( ) {
2024-05-20 11:00:45 -04:00
if self . v [ pos ] < self . v [ child0 ] { pivot = child0 ; }
2024-05-09 09:52:52 -10:00
if child1 < self . v . len ( ) {
2024-05-20 11:00:45 -04:00
if self . v [ pivot ] < self . v [ child1 ] { pivot = child1 ; }
2024-05-09 09:52:52 -10:00
}
if pivot ! = pos {
self . v . swap ( pivot , pos ) ;
self . trickle_down ( pivot ) ;
}
}
}
fn insert ( & mut self , item : T ) {
self . v . push ( item ) ;
self . bubble_up ( self . v . len ( ) - 1 ) ;
}
fn pop ( & mut self ) -> Option < T > {
if self . v . len ( ) = = 0 { None }
else {
let end = self . v . len ( ) - 1 ;
self . v . swap ( 0 , end ) ;
let rval = self . v . pop ( ) ;
self . trickle_down ( 0 ) ;
rval
}
}
fn dump ( & self ) {
for index in 0 .. self . v . len ( ) {
self . v [ index ] . dump ( ) ;
}
}
}
2024-05-26 08:19:55 -04:00
impl Market {
fn exercise ( & mut self ) {
let mut rng : StdRng = StdRng ::seed_from_u64 ( 13 u64 ) ;
2024-05-30 22:22:02 -04:00
let teppy = self . register_trader ( " Teppy " ) ;
let luni = self . register_trader ( " Luni " ) ;
2024-06-23 18:50:48 -04:00
let usd = self . register_asset ( " USD " ) . unwrap ( ) ;
let btc = self . register_asset ( " BTC " ) . unwrap ( ) ;
2024-05-30 22:22:02 -04:00
self . add_trader_balance ( teppy , btc , 100000. into ( ) ) ;
self . add_trader_balance ( luni , usd , 650000000. into ( ) ) ;
let mut count = 0 ;
let mut tries = 0 ;
2024-06-03 19:36:51 -04:00
for _i in 1 ..= 1000000 {
2024-05-26 08:19:55 -04:00
let seller = if rng . gen_bool ( 0.5 ) { teppy } else { luni } ;
2024-05-30 22:22:02 -04:00
let ( buy_type , sell_type , buy_qty , sell_qty ) :( usize , usize , FiNum , FiNum ) ;
2024-05-26 08:19:55 -04:00
if rng . gen_bool ( 0.5 ) {
sell_type = btc ;
buy_type = usd ;
sell_qty = rng . gen_range ( 1 ..= 5 ) . into ( ) ;
buy_qty = sell_qty * rng . gen_range ( 60 ..= 70 ) . into ( ) ;
} else {
sell_type = usd ;
buy_type = btc ;
buy_qty = rng . gen_range ( 1 ..= 5 ) . into ( ) ;
sell_qty = buy_qty * rng . gen_range ( 60 ..= 70 ) . into ( ) ;
}
2024-05-26 20:37:08 -04:00
let mut _success = false ;
if self . make_order ( seller , sell_type , buy_type , sell_qty , buy_qty ) { count + = 1 ; _success = true ; } ;
2024-05-30 22:22:02 -04:00
if count > = 1000000 { break ; }
2024-05-26 08:19:55 -04:00
tries + = 1 ;
}
println! ( " Tries: {} Trades: {} " , tries , count ) ;
self . sanity_check ( ) ;
}
}
2024-05-30 22:22:02 -04:00
fn wt_level ( index :usize ) -> usize {
( index ^ ( index + 1 ) ) . trailing_ones ( ) as usize - 1
2024-05-26 08:19:55 -04:00
}
2024-06-03 19:36:51 -04:00
fn wt_leaf ( index :usize ) -> bool {
index & 1 = = 0
}
2024-05-30 22:22:02 -04:00
fn wt_left ( index :usize ) -> Option < usize > {
2024-05-26 08:19:55 -04:00
let level = wt_level ( index ) ;
if level > 0 { Some ( index - ( 1 < < ( wt_level ( index ) - 1 ) ) ) } else { None }
}
2024-06-12 18:29:44 -04:00
fn wt_right_edge ( index : usize , edge : usize ) -> Option < usize > { // Less than edge
if index & 1 = = 0 { None }
else {
let mut r = wt_right ( index ) . unwrap ( ) ;
2024-06-13 17:47:00 -04:00
if r < edge { Some ( r ) }
else {
while r & 1 = = 1 {
if r < edge { return Some ( r ) ; }
2024-06-12 18:29:44 -04:00
else { r = wt_left ( r ) . unwrap ( ) ; }
2024-06-13 17:47:00 -04:00
}
2024-06-12 18:29:44 -04:00
if r < edge { Some ( r ) } else { None }
2024-06-13 17:47:00 -04:00
}
}
2024-06-11 17:44:11 -04:00
}
2024-05-30 22:22:02 -04:00
fn wt_right ( index :usize ) -> Option < usize > {
2024-05-26 08:19:55 -04:00
let level = wt_level ( index ) ;
if level > 0 { Some ( index + ( 1 < < ( wt_level ( index ) - 1 ) ) ) } else { None }
}
2024-05-30 22:22:02 -04:00
fn wt_parent ( index :usize ) -> usize {
2024-05-26 08:19:55 -04:00
let lev = wt_level ( index ) ;
let first_in_row = index % ( 1 < < lev ) ;
let skip = 2 < < lev ;
let nth_in_row = ( index - first_in_row ) / skip ;
let first_in_parent_row = ( 2 < < lev ) - 1 ;
let skip_in_parent_row = 4 < < lev ;
let nth_in_parent_row = nth_in_row > > 1 ;
first_in_parent_row + nth_in_parent_row * skip_in_parent_row
}
2024-05-13 12:03:03 -04:00
2024-05-30 22:22:02 -04:00
fn wt_forefather ( max_index :usize ) -> usize {
2024-05-26 20:37:08 -04:00
let mut rval = max_index ;
rval = rval | ( rval > > 1 ) ;
rval = rval | ( rval > > 2 ) ;
rval = rval | ( rval > > 4 ) ;
rval = rval | ( rval > > 8 ) ;
rval = rval | ( rval > > 16 ) ;
rval = rval | ( rval > > 32 ) ;
if rval > max_index { wt_left ( rval ) . unwrap ( ) } else { rval }
}
2024-05-26 08:19:55 -04:00
fn tree_stuff ( ) {
for i in ( 0 ..= 60 ) . step_by ( 1 ) {
2024-05-26 20:37:08 -04:00
println! ( " Index {} Forefather {} Parent {} " , i , wt_forefather ( i ) , wt_parent ( i ) ) ;
2024-05-30 22:22:02 -04:00
}
2024-05-26 08:19:55 -04:00
}
2024-05-09 09:52:52 -10:00
2024-06-03 19:36:51 -04:00
fn royalty_stuff ( ) {
let mut rt = RoyaltyTree ::new ( ) ;
2024-06-13 22:51:32 -04:00
for index in 0 .. 10 {
2024-06-13 17:47:00 -04:00
rt . add_weight ( index , FiNum ::new_i32 ( 10 ) ) ;
rt . add_royalty ( FiNum ::new_i32 ( 24 ) )
}
2024-06-03 19:36:51 -04:00
for index in 0 .. rt . tree . len ( ) {
2024-06-11 17:44:11 -04:00
println! ( " Index: {} Weight_here {} Weight_below {} Weight_here_below {} " , index , rt . weight_here ( index ) , rt . weight_below ( index ) , rt . weight_here_below ( index ) ) ;
2024-06-03 19:36:51 -04:00
}
2024-05-26 08:19:55 -04:00
}
2024-05-13 12:03:03 -04:00
2024-06-20 16:22:08 -04:00
fn process_file ( fname : & str ) {
println! ( " Processing file: {} " , fname )
}
2024-06-23 18:50:48 -04:00
fn interactive ( m : & mut Market ) {
println! ( " Trading interactively in Tuesday Markets (demo) " ) ;
2024-06-20 16:22:08 -04:00
let stdin = io ::stdin ( ) ;
2024-06-23 18:50:48 -04:00
let mut trader :usize = 0 ;
2024-06-20 16:22:08 -04:00
for line in stdin . lock ( ) . lines ( ) {
2024-06-23 18:50:48 -04:00
match line {
Ok ( input ) = > {
let tokens : Vec < & str > = input . split_whitespace ( ) . collect ( ) ;
match tokens . as_slice ( ) {
[ " dump " ] = > m . dump ( ) ,
[ " 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 ) } ,
[ " whoami " ] = > { println! ( " Logged in as {} , id {} " , m . traders [ trader ] . name , trader ) ; }
[ " addtrader " , username ] = > { let id = m . register_trader ( username ) ; println! ( " Added user {} as id {} " , username , id ) ; } ,
[ " balances " ] = > {
println! ( " Balances for trader {} " , m . traders [ trader ] . name ) ;
for ( key , value ) in & m . traders [ trader ] . balances { println! ( " {} {} " , m . number_to_name ( * key ) , value ) ; }
}
[ " addasset " , assetname ] = > {
if let Some ( cur ) = m . register_asset ( assetname ) { println! ( " Added asset {} " , m . number_to_name ( cur ) ) }
else { println! ( " Asset {} already exists. " , assetname ) }
}
[ " addfunds " , username , qty0 , cur0 ] = > {
let id = m . trader_name2num . get ( * username ) ;
let qty = FiNum ::new_str ( qty0 ) ;
let cur = m . name_to_number ( cur0 ) ;
if id . is_none ( ) { println! ( " Could not find trader {} " , username ) ; }
else if qty . is_zero ( ) { println! ( " Could not parse quantity {} " , qty0 ) }
else if cur . is_none ( ) { println! ( " Could not find asset {} " , cur0 ) }
else {
let id = * id . unwrap ( ) ;
let cur = * cur . unwrap ( ) ;
m . add_trader_balance ( id , cur , qty ) ;
println! ( " Added {} {} to {} " , qty , m . number_to_asset ( cur ) . name , m . traders [ id ] . name )
}
}
[ " order " , qty0 , cur0 , qty1 , cur1 ] = > {
let qty0 = FiNum ::new_str ( qty0 ) ;
let cur0 = m . name_to_number ( cur0 ) ;
let qty1 = FiNum ::new_str ( qty1 ) ;
let cur1 = m . name_to_number ( cur1 ) ;
if ! qty0 . is_zero ( ) & & cur0 . is_some ( ) & & ! qty1 . is_zero ( ) & & cur1 . is_some ( ) {
m . make_order ( trader , * cur0 . unwrap ( ) , * cur1 . unwrap ( ) , qty0 , qty1 ) ;
}
}
[ " quit " ] = > {
break ;
}
_ = > println! ( " Invalid command. Please try again. " ) ,
2024-06-20 16:22:08 -04:00
}
}
2024-06-23 18:50:48 -04:00
Err ( error ) = > println! ( " Error reading input: {} " , error ) ,
2024-06-20 16:22:08 -04:00
}
}
2024-06-23 18:50:48 -04:00
}
fn erase ( filename : & str ) {
// Stub function for erasing a file
println! ( " Erasing file: {} " , filename ) ;
}
fn copy ( source : & str , destination : & str ) {
// Stub function for copying a file
println! ( " Copying file from {} to {} " , source , destination ) ;
}
2024-06-20 16:22:08 -04:00
2024-05-09 09:52:52 -10:00
fn main ( ) {
2024-05-26 08:19:55 -04:00
let args : Vec < String > = env ::args ( ) . collect ( ) ;
2024-06-20 16:22:08 -04:00
let mode = if args . len ( ) < = 1 { " --interactive " } else { args [ 1 ] . as_str ( ) } ;
2024-05-26 20:37:08 -04:00
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
2024-05-26 08:19:55 -04:00
match mode {
2024-06-23 18:50:48 -04:00
" --interactive " = > interactive ( & mut m ) ,
2024-05-26 08:19:55 -04:00
" --exercise " = > m . exercise ( ) ,
2024-05-30 22:22:02 -04:00
" --treestuff " = > tree_stuff ( ) ,
2024-06-13 17:47:00 -04:00
" --royaltystuff " = > royalty_stuff ( ) ,
2024-05-30 22:22:02 -04:00
_ = > println! ( " Unknown mode: {} " , mode ) ,
}
2024-05-26 08:19:55 -04:00
}