<?php
// (C) 2000 LinuxFutures.com, Inc.
//
// Part of UPmarkets - the software behind the LinuxFutures game site
// visit www.LinuxFutures.com to play
//
// We are making the software available to you under the GNU General Public License,
// a copy of which should accompany this software in the file LICENSE.
//
// A web-based copy of the LICENSE is located at http://www.gnu.org/copyleft/gpl.txt
//
// While there is no charge for using this software, there are important restrictions.
//
// This LICENSE does not allow, in general, proprietary modifications or proprietary derivative works.
// If you base new commercial products on our work, great, but you have to give them away just as we did.
//
// This software carries ABSOLUTELY NO WARRANTY. It is offered AS-IS, and may not work at all
// or may have harmful or hazardous side effects.
//
//
// -------------------- what this file does ---------------------
// provides function pricing_commit($sym, $pricing_array)
// also provides helper functions pricing_settle_* used by pricing_commit
// commits a pricing to the database
// updates tables pricings, pricings_recent, quotes_filled, and ledgers
//
// THIS FUNCTION SHOULD BE CALLED WITH _AT LEAST_ the locks mentioned below
// LOCK TABLES ledgers, partners, pricings, pricings_latest, quotes, quotes_filled WRITE policies READ;
//
// Pricing array is expected to be from f_economy_uniform_pricing_array, or some other
// function that returns the same data. Fields used: price, quantity, partial, partialQ
//
// Important: usually, after running pricing_commit, you'll probably want to run
// users_check_bankruptcy and users_check_panic
//
//
require('inc.d/f_pricing_sanity.inc');
function pricing_settle_all($posted, $buy_sell_none, $price, $com, $where) {
global $db_link;
$ins = "INSERT INTO quotes_filled (pricing_posted,quote_posted,fill_type,fill_quantity) ";
$bs = " SELECT ";
$bs .= "'".$posted."' as pricing_posted, ";
$bs .= "posted as quote_posted, ";
$bs .= "'".$buy_sell_none."' as fill_type, ";
$bs .= "quantity as fill_quantity ";
$bs .= "FROM quotes ";
$none = " SELECT ";
$none .= "'".$posted."' as pricing_posted, ";
$none .= "posted as quote_posted, ";
$none .= "'none' as fill_type, ";
$none .= "0 as fill_quantity ";
$none .= "FROM quotes ";
if (strcmp("none",$buy_sell_none) == 0){
$sql = $ins.$none.$where.";";
} else {
$sql = $ins.$bs.$where.";";
}
$r = mysql_query($sql, $db_link);
mysql_error_sanity("f_pricing_commit pricing_settle_all insert quotes_filled");
if (strcmp("none", $buy_sell_none) == 0) { return; } // all done for none's.
$ins = "INSERT INTO ledgers (userid,symbolid,amount,posted,why) ";
$buy = " SELECT ";
$buy .= "userid, ";
$buy .= "symbolid, ";
$buy .= "quantity as amount, ";
$buy .= "'".$posted."' as posted, ";
$buy .= "'your buy executed' as why ";
$buy .= "FROM quotes ";
$sell = " SELECT ";
$sell .= "userid, ";
$sell .= "symbolid, ";
$sell .= "(-1 * quantity) as amount, ";
$sell .= "'".$posted."' as posted, ";
$sell .= "'your sell executed' as why ";
$sell .= "FROM quotes ";
if (strcmp("buy", $buy_sell_none) == 0) {
$sql = $ins.$buy.$where.";";
} elseif (strcmp("sell",$buy_sell_none) == 0) {
$sql = $ins.$sell.$where.";";
} else { exit; }
$r = mysql_query($sql, $db_link);
mysql_error_sanity("f_pricing_commit pricing_settle_all insert ledgers symbol");
// now move the payment
$ins = "INSERT INTO ledgers (userid,symbolid,amount,posted,why) ";
$buy = " SELECT ";
$buy .= "userid, ";
$buy .= "1 as symbolid, "; // symbolid=1 reserved for money, Tux Nuggets, etc.
$buy .= "(".(-$price)." * quantity ) as amount, ";
$buy .= "'".$posted."' as posted, ";
$buy .= "'your buy executed' as why ";
$buy .= "FROM quotes ";
$sell = " SELECT ";
$sell .= "userid, ";
$sell .= "1 as symbolid, "; // symbolid=1 reserved for monet, Tux Nuggets, etc.
$sell .= "(".$price." * quantity) as amount, ";
$sell .= "'".$posted."' as posted, ";
$sell .= "'your sell executed' as why ";
$sell .= "FROM quotes ";
if (strcmp("buy", $buy_sell_none) == 0) {
$sql = $ins.$buy.$where.";";
} elseif (strcmp("sell",$buy_sell_none) == 0) {
$sql = $ins.$sell.$where.";";
}
$r = mysql_query($sql, $db_link);
mysql_error_sanity("f_pricing_commit pricing_settle_all insert ledgers payment");
// now pay the commission
$acom = $price * $com;
$pay = " SELECT ";
$pay .= "userid, ";
$pay .= "1 as symbolid, "; // symbolid=1 reserved for money, Tux Nuggets, etc.
$pay .= "-FLOOR( ".$acom." * quantity / 100) as amount, ";
$pay .= "'".$posted."' as posted, ";
$pay .= "'commission' as why ";
$pay .= "FROM quotes ";
$r = mysql_query($ins.$pay.$where.";", $db_link);
mysql_error_sanity("f_pricing_commit pricing_settle_all insert ledgers commission");
}
function pricing_settle_one($posted,$buy_sell_none,$price,$com,$quote) {
global $db_link;
if (strcmp($buy_sell_none,"buy") == 0) {
$cashflowsign = -1;
} elseif (strcmp($buy_sell_none,"sell") == 0) {
$cashflowsign = 1;
} else {
echo "bad parms f_pricing_commit pricing_settle_one"; exit;
}
$fill_type = $buy_sell_none;
$ins = "INSERT INTO quotes_filled (pricing_posted,quote_posted,fill_type,fill_quantity) ";
$ins .= " VALUES ('".$posted."','".$quote["posted"]."','".$fill_type."',".$quote["quantity"].");";
mysql_query($ins, $db_link);
mysql_error_sanity("f_pricing_commit.inc settle_one quotes ");
$ins = "INSERT INTO ledgers (userid,symbolid,amount,posted,why) ";
$ins .= " VALUES (";
$ins .= $quote["userid"].",";
$ins .= $quote["symbolid"].",";
$ins .= (-1 * $cashflowsign * $quote["quantity"]).",";
$ins .= "'".$posted."',";
$ins .= "'".$buy_sell_none." executed'";
$ins .= ");";
mysql_query($ins, $db_link);
mysql_error_sanity("f_pricing_commit.inc settle_one ledgers symbol ");
$ins = "INSERT INTO ledgers (userid,symbolid,amount,posted,why) ";
$ins .= " VALUES (";
$ins .= $quote["userid"].",";
$ins .= " '1' ,";
$ins .= ($cashflowsign * $price * $quote["quantity"]).",";
$ins .= "'".$posted."',";
$ins .= "'".$buy_sell_none." executed'";
$ins .= ");";
mysql_query($ins, $db_link);
mysql_error_sanity("f_pricing_commit.inc settle_one ledgers money ");
// pay the commission
$ins = "INSERT INTO ledgers (userid,symbolid,amount,posted,why) ";
$ins .= " VALUES (";
$ins .= $quote["userid"].",";
$ins .= " '1' ,";
$ins .= -floor(($price.$com.$quote["quantity"])/100).",";
$ins .= $posted.",";
$ins .= "'".$buy_sell_none." executed'";
$ins .= ");";
}
function pricing_settle_limitQ($posted, $buy_sell, $price, $com, $where, $limitq) {
global $db_link;
$sel = "SELECT posted, symbolid, userid, quantity FROM quotes ";
$order = " ORDER BY posted ASC;";
$r = mysql_query($sel.$where.$order, $db_link);
$number_of_rows = mysql_num_rows($r);
// find the quote that gets partially filled
for( $i=0; ( ($i < $number_of_rows) && ($limitq > 0) ); $i++) {
$quote = mysql_fetch_array($r);
if ($limitq < $quote["quantity"]){ $fillq = $limitq; } // fillq is the quantity to fill from this quote.
$limitq -= $quote["quantity"];
}
mysql_free_result($r);
$quote["quantity"] = $fillq;
pricing_settle_one($posted,$buy_sell,$price,$com,$quote); // settle the partial fill
// the priority rule for partial fills at a constant price is first come, first served.
// thus everyone earlier than the partially filled quote gets to trade
// and no one whose quote was posted later than the partially filled quote.
$higher = " AND posted < '".$quote["posted"]."' ";
$lower = " AND posted > '".$quote["posted"]."' ";
pricing_settle_all($posted, $buy_sell, $price, $com, $where.$higher);
pricing_settle_all($posted, "none", $price, $com, $where.$lower);
}
function pricing_commit($sym="0", $pricing_array, $commentary="-", $commentary_by="0") {
global $db_link;
$symbolid = (int) $sym; if ($symbolid <= 0) { exit; }
if ($pricing_array["quantity"] <= 0) { return(0); }
$r = mysql_query("select now() as now;", $db_link);
mysql_error_sanity("f_pricing_commit now() ");
$posted = addslashes(mysql_result($r,0,0));
mysql_free_result($r);
$policy = policy_array($symbolid);
$com = $policy["commission"]; if ($com > 5){ $com = 5; }
$price = $pricing_array["price"];
$partial = $pricing_array["partial"];
$partialQ = $pricing_array["partialQ"];
$where = " WHERE active=1 AND symbolid=".$symbolid." ";
$buygt = " AND buy_price > ".$price." ";
$buyeq = " AND buy_price = ".$price." ";
$buylt = " AND buy_price < ".$price." ";
$selllt = " AND sell_price < ".$price." ";
$selleq = " AND sell_price = ".$price." ";
$sellgt = " AND sell_price > ".$price." ";
// these always get filled
pricing_settle_all($posted,"buy",$price,$com,$where.$buygt);
pricing_settle_all($posted,"sell",$price,$com,$where.$selllt);
// these never get filled
pricing_settle_all($posted,"none",$price,$com,$where.$buylt.$sellgt);
// note that this is an AND, not an OR. we need AND to avoid duplicates
// for the equals cases, we need to check the partial fill indicator
// and if it is present, use limitqs.
if ($partial) {
if (strcmp("D",$partial) == 0) {
pricing_settle_limitQ($posted,"buy",$price,$com,$where.$buyeq,$partialQ);
pricing_settle_all($posted,"sell",$price,$com,$where.$selleq);
} elseif (strcmp("S",$partial) == 0) {
pricing_settle_all($posted,"buy",$price,$com,$where.$buyeq);
pricing_settle_limitQ($posted,"sell",$price,$com,$where.$selleq,$partialQ);
}
} else { // matches no partials -- complete fill of the eqs
$partial = "N"; $partialQ = '0';
pricing_settle_all($posted, "buy", $price, $com, $where.$buyeq );
pricing_settle_all($posted, "sell", $price, $com, $where.$selleq );
}
// pay the commission to the market chairperson and partners
partners_transfer_money($symbolid,floor($quantity*$price*$com/100),"commission received market ".$symbolid);
// reset all the quotes that are one shot to inactive status - whether they execute or not
$sql = "UPDATE quotes SET active=0 WHERE symbolid=".$symbolid." AND repeat=0;";
mysql_query($sql, $db_link);
mysql_error_sanity("f_pricing_commit update deactivate nonrepeating quotes");
// ok now we are done with ledgers, fills, and quotes
// so now let's put a record in the pricings database
$sql = "INSERT INTO pricings (posted,symbolid,price,quantity,crossing_type,partial_side,partialQ,p0,p1,q0,q1,commentary,commentary_by) VALUES ";
$sql .= "('".$posted."',";
$sql .= $symbolid.",";
$sql .= $price.",";
$sql .= $pricing_array["quantity"].",";
$sql .= "'".$pricing_array["crossing_type"]."',";
$sql .= "'".$partial."',";
$sql .= $partialQ.",";
$sql .= $pricing_array["p0"].",";
$sql .= $pricing_array["p1"].",";
$sql .= $pricing_array["q0"].",";
$sql .= $pricing_array["q1"].",";
$sql .= "'".addslashes($commentary)."',";
$sql .= "'".addslashes($commentary_by)."'";
$sql .=");";
mysql_query($sql, $db_link);
mysql_error_sanity("f_pricing_commit insert pricings");
pricing_sanity($symbolid); // update pricings_latest
}