/jesus/setup.php
PHP | 1417 lines | 802 code | 292 blank | 323 comment | 78 complexity | d6fbc38e53043cd96aeef6da9e832e5a MD5 | raw file
- <?php
-
-
- class setup
- {
- private $check, $setup_settings, $setup_propositions;
-
-
- public function environment( $account_info )
- {
- /*
- * CONCEPT:
- * setup() does most of the things needed to setup an environment to run jesus.
- *
- * CAUTION:
- * There are a lot of tables, globals and rules. setup() must be coded to check
- * to make sure everything is set up correctly because the user will forget the
- * settings after a few months and we want to reduce the impact of human error.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $this->check = new check();
-
- $this->set_account_globals( $account_info );
-
- display_tables( 'open_account' );
-
- // Connect to the database
- $this->connect();
-
- // Create the MySQL procedures (stored functions)
- $this->procedures();
-
- // Delete the tables after a number of test runs
- $this->delete_tables();
-
- // Create the static $port tables
- $this->tables();
-
- // Check to make sure the tables are all set up
- $this->check->tables();
-
- // Insert the settings based on $unique_account and defaults
- $this->insert_settings();
-
- // Make sure there is only ONE instance of jesus running at a time
- $this->lock( "lock", "jesus" );
-
- // Set the timestamp for this run
- $this->datetime();
-
- // Check to make sure the settings for the account are good
- $this->check->settings();
-
- // Set the globals (especially related to the brokerage account).
- $this->globals();
-
- // Setup the `propositions` table
- $this->propositions();
-
- // Update the degrees (and set $S->degrees for god)
- $this->degrees();
-
- // Release all of the temporary 'hold' stops for all positions
- $this->release_holds();
-
- // Get the account information from the broker
- $this->broker();
-
- // Check the cash_broker against the local tally
- $this->check->cash();
-
- // Divide the money among the $ports
- $this->communion();
-
- }
-
-
-
- public function accounts()
- {
- /*
- * CONCEPT:
- * setup->accounts() sets the account unique arrays.
- *
- * CAUTION:
- * If satan is running, $S->unique_accounts is replaced with $S->satan_unique_accounts
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- comment( "Setting up the unique accounts (on " . $S->datetime . ") . . . ", 11 );
-
- // If the backtest system is running
- if( $S->backtesting === 'yes' )
- {
- // If backtest is running use it's accounts and databases
- $unique_accounts = $S->backtest_account;
- }
- elseif( $S->satanrunning === 'yes' )
- {
- // If satan is running use it's accounts and databases
- $unique_accounts = $S->satan_unique_accounts;
- }
- else
- {
- // Include the client accounts
- require_once('accounts.php');
- }
-
- // Check to make sure the accounts are unique and have valid settings
- $check->account_uniqueness( $unique_accounts );
-
- comment( "Done.", 7 );
-
- return $unique_accounts;
- }
-
-
-
- private function benchmark( $clear = false )
- {
- /*
- * CONCEPT:
- * benchmark() uses the php function microtime() which is the "wall clock" time
- * that passes while the entire process is running (including the time it takes
- * to log in and get quotes from the broker). When jesus is called by backtest,
- * the benchmark() function is started at the top of backtest.php (rather than
- * inside jesus (so that the entire backtest run time is recorded).
- *
- * CAUTION:
- * Only one benchmark time is recorded at a time. Estimating the time it takes
- * to do multiple runs (in backtest) may be hard unless a table is created and
- * more benchmark times are stored so that an average can be calculated.
- */
-
-
- // Make $stime static so that it cannot be overwritten
- static $starttime;
-
- // Call the php function microtime()
- $currentTime = microtime( TRUE );
- $benchmark = '';
- // If $starttime has been set previously
- if( $starttime && !$clear )
- {
- // Calculate the time lapse between the current time and the start time
- $benchmark = $currentTime - $starttime;
-
- // Round the time to 2 decimal places
- $benchmark = round( $benchmark, 2 );
-
- comment( "Elapsed time: $benchmark seconds\n", 9 );
- }
-
- // Set the starting time
- $starttime = $currentTime;
-
- return $benchmark;
- }
-
-
-
- private function broker()
- {
- /*
- * CONCEPT:
- * broker() gives an account of the current information in the brokerage account.
- * Except for login, the other variables are returned in multi-demensional arrays.
- *
- * CAUTION:
- * Note: just2trade will give back information about all accounts for the client.
- * Also, the information for all $ports is included as well.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- // Instantiate the class that sets up the environment
- $setup = new setup();
-
-
- comment( "Running with spiritmode = [ " . $S->spiritmode . " ] ", 6 );
-
- if( $S->satanrunning !== 'yes' )
- {
- // Set the file jesus will use for spirit . . .
- if( $S->spiritmode === 'succubus' || $S->spiritmode === 'demon' )
- {
- require_once('../spirit/demon.php');
- }
- elseif( $S->spiritmode === 'broker' )
- {
- require_once('../spirit/broker.php');
- }
- }
-
- // Instantiate the correct version of spirit
- $spirit = $setup->spirit();
-
- comment( "Aquiring all account attributes . . . ", 8 );
-
- // Unset the superglobals that are about to be retrieved
- $unsets = array('logged_in', 'open_market', 'cash_broker', 'broker_positions', 'done_orders', 'open_orders');
-
- // Loop through the unsets array and unset
- foreach( $unsets AS $key => $superglobal )
- {
- unset( $S->$superglobal );
- }
-
- // If the variation1 and variation2 values are set
- if( $S->variation1 && $S->variation2 )
- {
- // Get all of the current information from the brokerage account
- list( $logged_in, $open_market, $cash_broker, $broker_positions, $done_orders, $open_orders ) =
- $spirit->acquire_all_account_attributes();
- }
-
- // Check the variables returned from the broker()
-
- $S->logged_in = $logged_in;
- $S->open_market = $open_market;
- $S->cash_broker = $cash_broker;
-
- // Check the $broker_positions values
- $check->symbol_array( $broker_positions, 'broker_positions', 9 );
-
- // Check the $done_orders values
- $check->symbol_array( $done_orders, 'done_orders', 9 );
-
- // Check the $open_orders values
- $check->symbol_array( $open_orders, 'open_orders', 9 );
-
- comment("logged_in = [ $S->logged_in ] open_market = [ $S->open_market ] cash_broker = [ $S->cash_broker ] ", 9 );
-
- // Update the cash_broker to match the cash_local
- sql( "UPDATE `settings` SET value = '" . $S->cash_broker . "'
- WHERE name = 'cash_broker' ", "setup->broker" );
-
- comment("Recorded cash_broker = [ \$" . $S->cash_broker . " ] ", 6 );
-
- comment( "Done.", 7 );
- }
-
-
-
- private function cash_reserve()
- {
- /*
- * CONCEPT:
- * setup->cash_reserve() calculates the amount of cash that should set aside for slippage initially.
- * It is easy to remember to set aside money for the cash_reserve; It will be factored in during the
- * backtesting (which will determine the optimal minimal amount of cash required to make a profit).
- *
- * CAUTION:
- * This should only be run ONCE when first setting up the tables because it stores cash_slippage in
- * the `settings` table. The cash_slippage value is updated to reflect the amount of cash_slippage.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- comment("Calculating the \$S->cash_reserve that will be set aside for slippage . . .", 6);
-
- // Set the cash_reserve percent as a decimal
- $cash_reserve_percent = $S->cash_reserve_percent / 100;
-
- // Deduct the cash that cannot be invested by god
- $spendable_cash = $S->cash_broker - $S->cash_safe;
-
- comment("[ \$$S->cash_broker ] cash_broker - [ \$$S->cash_safe ] cash_safe = [ $spendable_cash ] spendable cash. ", 5);
-
- // Multiply the spendable_cash by the result ( $1000 X 0.10 = $100 )
- // Floor the $cash_reserve (at 2 decimal places) to get the initially reserved cash
- $cash_reserve = floor_decimal( $spendable_cash * $cash_reserve_percent , 2);
-
- // Set the initial cash_slippage
- sql("UPDATE `settings` SET value = '" . $cash_reserve . "'
- WHERE name = 'cash_slippage' ", "setup->cash_reserve");
-
- comment("[ \$$cash_reserve ] has been set aside for cash_slippage. ", 7);
-
- comment( "Done. ", 7 );
- return $cash_reserve;
- }
-
-
-
- private function communion()
- {
- /*
- * CONCEPT:
- * communion() runs ONE time before we start investing. It divides $S->cash_broker
- * (which comes directly from the brokerage account) or $S->test_cash_broker which
- * comes from configure() among the $S->ports (after subtracting the $S->cash_safe
- * and $S->cash_reserve).
- *
- * CAUTION:
- * It is important to get the total free cash amount from the brokerage account.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Tally the starting_cash for all of the ports
- list( $cash_port ) = mysql_fetch_row( sql( "SELECT `value` FROM `settings`
- WHERE name = 'cash_port' LIMIT 1 ", "setup->communion" ) );
-
- if( $cash_port === 'run_communion' )
- {
- // Reserve some cash for (the initial) slippage
- $cash_reserve = $this->cash_reserve();
-
- comment( "Dividing the money among the \$ports . . . ", 7 );
-
- // Calculate the starting cash for each $port.
- // Floor the $total_starting_cash to the penny
- $S->port_cash = floor_decimal( ( ( $S->cash_broker
-
- // Deduct the money god is not allowed to spend ever.
- - $S->cash_safe
-
- // Deduct the money god will have as an initial slippage buffer.
- - $cash_reserve ) / $S->ports ), 2 );
-
- comment( "Distributing ([ \$$S->cash_broker ] cash_broker - [ \$$S->cash_safe ] cash_safe
- - [ \$$cash_reserve ] cash_reserve ) / [ $S->ports ] ports = [ \$$S->port_cash ] to each port. ", 5);
-
- // Distribute the money to the ports
- sql( "UPDATE `settings` SET value = '" . $S->port_cash . "'
- WHERE name = 'port_cash' ", "setup->communion" );
-
- // Permanently record the initial port_cash value in `settings` 'cash_port'. cash_port is never overwritten.
- sql( "UPDATE `settings` SET value = '" . $S->port_cash . "'
- WHERE name = 'cash_port' ", "setup->communion" );
- }
- else
- {
- comment("The investment capital has already been divided among the ports ", 5 );
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- public function connect()
- {
-
- /*
- * CONCEPT:
- * connect() connects to the database of the server running jesus.
- * It has a variable ($server) that can be changed to switch the server connection code.
- *
- * CAUTION:
- * Remember to change the passwords after production for higher security.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Initialize var
- $server = '';
-
- comment( "" . $S->fullname . " ", 11 );
-
- comment( "[ database: " . $S->database . " ]. . . ", 8 );
-
- // Set this variable to specify which server is being used (programmer | shared | shared)
- // [EDIT]: 1. Comment the following line (and uncomment the subsequent line).
- // $server = 'shared';
- // $server = 'programmer';
- // Make sure you set up MySQL to use the InnoDB database engine.
- if( $server == 'programmer' )
- {
- // [EDIT] Set the Programmer's server settings. Simply fill in your mySQL database user and password.
- $db_server = 'localhost';
- $db_user = 'root';
- $db_pass = '';//1111';
- }
- elseif( $server == 'shared' )
- {
- // Shared Production Server
- $db_server = 'changinglinks1.globatmysql.com';
- $db_user = 'shortay';
- $db_pass = '4sho';
- }
- else
- {
- // My Production MySQL Server
- $db_server = 'localhost';
- $db_user = 'root';
- $db_pass = 'OlV734A';
- }
-
- comment( "database server = [ $db_server ] database = [ " . $S->database . " ]
- db_user = [ $db_user ] db_pass = [ $db_pass ] ", 2 );
-
- // Connect to the mySQL server
- mysql_connect( "$db_server", "$db_user", "$db_pass" ) or die( "Unable to connect to server!" );
-
- // Create the database that corresponds with the account set in configure
- sql( "CREATE DATABASE IF NOT EXISTS " . $S->database . " ", "createdatabase" );
-
- mysql_select_db( $S->database ) or die( "Could not select database (" . $S->database . ") using [ $server ] connection code" );
-
- }
-
-
-
- private function cssheader()
- {
- /*
- * CONCEPT:
- *
- * CAUTION:
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- if( $S->debug_detail <= 10 && $S->debug == 'yes' )
- {
- echo "<html><head><style> ";
-
- echo "body { font-family: Arial, sans-serif; font-size: 11pt; color: black; } ";
-
- echo ".header { font-weight: bold; font-size:11pt; } ";
-
- echo ".normal { color: #000000; font-size:11pt; } ";
-
- echo ".satan { color: #973bed; background-color:#b2fdf9; } ";
-
- echo ".N1 { color: #E3E3E3; font-size:8pt; } ";
- echo ".N2 { color: #D4D4D4; font-size:9pt; } ";
- echo ".N3 { color: #C0C0C0; font-size:10pt; } ";
- echo ".N4 { color: #B0B0B0; font-size:10pt; } ";
- echo ".N5 { color: #A1A1A1; font-size:11pt; } ";
- echo ".N6 { color: #808080; font-size:12pt; } ";
- echo ".N7 { color: #555555; font-size:12pt; } ";
- echo ".N8 { color: #000000; font-size:13pt; } ";
- echo ".N9 { color: #000000; font-size:14pt; } ";
- echo ".N10 { color:#FFFFFF; font-weight:bold; font-size:14pt; background-color:#69B000; }";
- echo ".N11 { color:#FFFFFF; font-weight:bold; font-size:14pt; background-color:#000000; }";
- echo ".N12 { color: #000000; font-size:13pt; background-color:#FFFFCC; } ";
-
- echo ".delimiter { color: #004080; font-weight: bold; } ";
-
- echo ".satandelimiter { color: #004080; font-weight: bold; font-size: large; } ";
-
- echo ".set { color:#000000 font-weight:bold; font-size:10pt; background-color:#FFFFCC; } ";
-
- echo ".data { color: #606060; font-size:11pt; } ";
-
- echo ".error { color: #C00000; } ";
-
- echo "</style></head><body>";
- }
- }
-
-
-
- public function datetime()
- {
- /*
- * CONCEPT:
- * setup->datetime() sets the timestamp to the real time (unless backtests are being run).
- * Otherwise, the datetime is set with dating->get_datetime(). That allows the backtest
- * system to set the date (rather than using the time stamp that is set with php or mySQL.
- * Relative time is used in sacrifice->daytrades_counter() & transactions->get_positions()
- * Note: Using setup->datetime() also makes sure the quote times are all syncronized.
- *
- * CAUTION:
- * There is a change the quotes table will not be updated with the current date.
- * Make sure the error checking stops jesus from processing without a good date.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- if( $S->backtesting !== 'yes' )
- {
- // Set the datetime
- $S->datetime = date("Y-m-d H:i:s");
- // Set the current date
- $S->date = date("Y-m-d");
- // Set the current time
- $S->time = date("H:i:s");
- }
-
- comment("The datetime is [ " . $S->datetime . " ] ", 7);
-
- // If there is no datetime by this time in the run, emergency()
- if( !$S->datetime )
- {
- emergency("\$S->datetime is set to [ " . $S->datetime . " ] ");
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- public function delete_tables()
- {
- /*
- * CONCEPT:
- * jesus creates the tables and adds data to them the first time it is run.
- *
- * CAUTION:
- * Make sure setup->delete_tables() is not used if $S->execute_transactions = 'yes'.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- // If the `settings` table exists . . .
- if( $check->table( 'settings' ) )
- {
- // Select the number of runs since the last table deletion
- list( $run_count ) = mysql_fetch_row( sql("SELECT `value`+1 FROM `settings`
- WHERE `name` = 'run_count' ", "setup->delete_tables" ) );
-
- // Set the run_count to 1 if it is not set
- $run_count = ( is_null($run_count) ) ? 1 : $run_count + 1;
-
- // Calculate the number of runs before the database will be deleted.
- $to_delete = $S->runs_to_delete_tables - $run_count;
-
- // Store the updated run_count
- sql( "UPDATE `settings` SET value=value+1
- WHERE name = 'run_count' ", "setup->delete_tables" );
-
- // Select execute_transactions
- list( $execute_transactions ) = mysql_fetch_row( sql( "SELECT value FROM `settings`
- WHERE name = 'execute_transactions' ", "setup->delete_tables" ) );
-
- if( $S->runs_to_delete_tables === $S->runs_to_delete_tables_max || $S->spiritmode === 'spirit' || $S->execute_transactions === 'yes' )
- {
- comment( "jesus has run [ $run_count ] times. setup->delete_tables() is disabled. ", 9 );
- }
- else
- {
- // If it is not time to delete yet . . .
- if( $run_count < $S->runs_to_delete_tables )
- {
- comment( "jesus has run [ $run_count ] times. ", 9 );
- comment( "Note: setup->delete_tables() is enabled.
- All database tables will be deleted after [ $to_delete ] more runs! ", 9 );
- }
- else
- {
- comment( "Starting over with a new `" . $S->database . "` database <hr color=#FF9900>", 9 );
-
- // List the global tables
- $tables = array('messages', 'port_counts', 'propositions', 'quotes', 'quoteshistory', 'replacements',
- 'selecta', 'settings', 'skippedtrans', 'subtransactions', 'transactions');
-
- comment( "Dropping the tables ", 7 );
-
- foreach( $tables AS $table )
- {
- comment( "Dropping table $table ", 5 );
-
- sql( "DROP TABLE IF EXISTS $table ", "setup->delete_tables" );
-
- if( $check->table( $table ) )
- {
- emergency( "`$table` ain't been deleted :( ");
- }
- }
- }
- }
- }
-
- comment( "Done.", 7 );
- }
-
-
-
- private function degrees()
- {
- /*
- * CONCEPT:
- * setup->degrees() pulls the positions and related degrees from the `positions` table,
- * validates the values, and adds them to the $S->degrees array.
- *
- * CAUTION:
- * setup->propositions() must be run before setup->degrees()
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- // Set an array to hold the degrees
- $S->degrees = array();
-
-
- // Count the number of positions with the degrees setup
- list( $degrees_setup ) = mysql_fetch_row(sql("SELECT IFNULL(COUNT('position'),0) FROM `propositions`
- WHERE `buydegree` = '0'
- OR `selldegree` = '0' ", "setup->degrees"));
-
- // If there are no degrees setup
- if( $degrees_setup !== '0' )
- {
- for( $port = 1; $port <= $S->ports; $port++ )
- {
- for( $position = 1; $position <= $S->positions; $position++ )
- {
- comment("Recording buydegree = [ " . $S->buydegree.$position . " ]
- selldegree = [ " . $S->selldegree.$position . " ]
- for port = [ $port ] position = [ $position ] ", 5);
-
- sql( "UPDATE `propositions` SET
- `buydegree` = '" . $S->buydegree.$position . "',
- `selldegree` = '" . $S->selldegree.$position . "'
- WHERE `port` = '" . $port . "'
- AND `position` = '" . $position . "' ", "setup->degrees" );
- }
- }
- }
-
- // Check the validity of each degree value
- $check->degrees();
-
- comment( "Done. ", 7 );
- }
-
-
-
- private function insert_settings()
- {
- /*
- * CONCEPT:
- * setup->insert_settings() records the settings array into the `settings` table.
- *
- * CAUTION:
- * Be careful not to let insert_settings() run twice on the same account.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Count the number of settings in the `settings` table
- list( $settings_rows ) = mysql_fetch_row(sql("SELECT IFNULL(COUNT('name'),0) FROM `settings`
- WHERE `name` NOT LIKE '%startdate%' ", "setup->insert_settings"));
-
- // If there are no settings (besides startdates)
- if( $settings_rows === '0' )
- {
- // Set an array of non-port settings
- foreach( $S->settings_defaults_values AS $i => $setting )
- {
- comment("Recording \$S->$setting as [ " . $S->$setting . " ]", 4 );
- sql( "INSERT INTO `settings` ( name, port, value ) VALUES ('" . $setting . "', '0', '" . $S->$setting . "' ) ", "setup->tables" );
- }
-
- foreach( $S->settings_all_ports_values AS $i => $setting )
- {
- comment("Recording \$S->$setting as [ " . $S->$setting . " ]", 4 );
- sql( "INSERT INTO `settings` ( name, port, value )
- VALUES ('" . $setting . "', '0', '" . $S->$setting . "' ) ", "setup->tables" );
- }
-
- if( $S->backtesting === 'yes' )
- {
- foreach( $S->settings_backtest_values AS $i => $setting )
- {
- comment("Recording \$S->$setting as [ " . $S->$setting . " ]", 4 );
- sql( "INSERT INTO `settings` ( name, port, value )
- VALUES ('" . $setting . "', '0', '" . $S->$setting . "' ) ", "setup->tables" );
- }
- }
-
- for( $port = 1; $port <= $S->ports; $port++ )
- {
- foreach( $S->settings_port_values AS $i => $setting )
- {
- comment("Recording \$S->$setting as [ " . $S->$setting . " ] for port [ $port ] ", 4 );
- sql( "INSERT INTO `settings` ( name, port, value )
- VALUES ('" . $setting . "', '" . $port . "', '" . $S->$setting . "' ) ", "setup->tables" );
- }
- }
-
- // sql( "ALTER TABLE `settings` ORDER BY `port`,`name` ", "setup->tables" );
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- public function globals()
- {
- /*
- * CONCEPT:
- * setup->globals() simply gets the global variable values from the `settings` table.
- *
- * CAUTION:
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- comment( "Setting the `settings` globals . . . ", 7 );
-
- // Select all of the jesus options globals
- $result = sql( "SELECT * FROM `settings`
- WHERE port IN ('0','" . $S->current_port . "') ", "setup->globals" );
-
- // Loop through the `settings` table and set each row as a global variable
- while( list( $variable, $port, $value ) = mysql_fetch_row( $result ) )
- {
- // Trim the value (in port there was a space in the database) and lowerport
- $variable = strtolower( $variable );
-
- // Add the variable and it's values to an array
- $S->$variable = $value;
-
- comment( "\$S->$variable = [ $value ] ", 6 );
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- public function lock( $switch, $who )
- {
- /*
- * CONCEPT:
- * lock() makes sure that only one instance is running by updating
- * the `settings` table.
- *
- * CAUTION:
- * It's very important that the tables are locked AND unlocked on time.
- * It is possible for god() to run as two instances. If god is started
- * two times it malfunctions by multiplying the numbers in the database.
- */
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Initialize var
- $mysqlerror = '';
-
- // Set the switch value (that will be recorded)
- if( $switch == "lock" )
- {
- $value = 'yes';
- }
- elseif( $switch == "unlock" )
- {
- $value = 'no';
- }
- else
- {
- emergency( "The lock value was [ $lock ]");
- }
-
- // If we are locking jesus (to make sure there is only one copy of god running)
- if( $who == "jesus" )
- {
- // Check if an instance of jesus is already running
- comment("$switch jesus.", 8);
-
- // Select the lock() value from the database
- sql( "SELECT GET_LOCK('jesus', 10)", "setup->lock" );
-
- $res = sql( "SELECT `value` FROM `settings`
- WHERE name = 'jesusrunning' ", "setup->lock" );
-
- if( $res === FALSE )
- {
- sql( "SELECT RELEASE_LOCK('jesus')", "setup->lock" );
- }
-
- // Make sure the lock value has been recorded
- $current_jesus_status = mysql_fetch_row( $res );
-
- if( !$current_jesus_status )
- {
- sql( "SELECT RELEASE_LOCK('jesus')", "setup->lock" );
-
- emergency( "The 'jesusrunning' option does not exist in the `settings` table ");
- }
-
- // If jesusrunning = yes
- if( $current_jesus_status[0] == 'yes' && $value == 'yes' )
- {
- // The jesus is already running. Quit.
- sql( "SELECT RELEASE_LOCK('jesus')", "setup->lock" );
-
- comment( "jesus is already running!", 9 );
-
- exit();
- }
-
- // If there is a problem with the locking sequence, emergency()
- elseif( $current_jesus_status[0] == 'no' && $value == 'no' )
- {
- sql( "SELECT RELEASE_LOCK('jesus')", "setup->lock" );
- emergency( "Trying to unlock jesus while it was not locked");
- }
-
- // Set the lock() value
- sql( "UPDATE `settings` SET `value` = '$value'
- WHERE name = 'jesusrunning' ", "setup->lock" );
-
- // Update the $S->jesusrunning (or backtest will halt)
- $S->jesusrunning = $value;
-
- sql( "SELECT RELEASE_LOCK('jesus')", "setup->lock" );
-
- // If jesus just did the final process ( unlock )
- if( $value == "no" )
- {
- // Now that all other processes are done, calculate the elapsed time.
- $benchmark = $this->benchmark();
-
- sql( "UPDATE `settings` SET `value` = '$benchmark' WHERE name = 'benchmark' ", "setup->lock" );
- }
- }
- // Check for any additional mysql errors
- if( $mysqlerror )
- {
- emergency( "MySQL error: [$mysqlerror]");
- }
- }
-
-
-
- public function preliminary()
- {
- /*
- * CONCEPT:
- * setup->preliminary() simply runs all of the misc stuff that should run
- * at the very start of the jesus process every time.
- *
- * CAUTION:
- */
-
-
- // Start timing jesus (if it has not been started by backtest or satan)
- $benchmark = $this->benchmark();
-
- // Make php errors show on the page if you are running from the browser
- // error_reporting( E_WARNING );
- // error_reporting( E_ALL | E_NOTICE );
-
- // Errors should be printed to the screen as part of the output (rather than hidden from the user)
- ini_set( 'display_errors', 1 );
-
- // Allow script to keep running if the browser disconnects
- ignore_user_abort( true );
-
- // Format the displayed output in the browser
- $this->cssheader();
-
- // Turn off the maximum execution time error
- set_time_limit(0);
- }
-
-
-
- private function procedures()
- {
- // Initialize var
- $function = '';
-
- // Check to see if the ROUND_COMMERCIAL procedure exists
- $result = mysql_query( "SHOW CREATE FUNCTION ROUND_COMMERCIAL " );
-
- // If the ROUND_COMMERCIAL MySQL function has been created
- if( $result )
- {
- list( $function, $sql_mode, $create_function ) = mysql_fetch_row( $result );
- }
-
- // If the function does NOT exist
- if( $function != 'ROUND_COMMERCIAL' )
- {
- // Create a function that uses more precise rounding
- sql( "CREATE FUNCTION
- ROUND_COMMERCIAL(value DOUBLE, preci INT(11))
- RETURNS DOUBLE NO SQL
- RETURN TRUNCATE((value * POW(10, preci)) + (IF(value = 0, 1,(value / ABS(value)))*(0.5 * POW(1, preci*-1))), 0) / POW(10, preci) ", "setup->procedures" );
- }
- }
-
-
-
- private function propositions()
- {
- /*
- * CONCEPT:
- * setup->propositions() makes sure there is a row for each position in each port
- * to store values related to the individual positions.
- *
- * CAUTION:
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- // If the tables were created on this run
- if( $this->setup_propositions === 'yes' )
- {
- // Insert all of the ports and positions in the propositions table
- if( $check->table( 'propositions' ) )
- {
- comment("Setting up placeholders for the propositions . . . ", 5);
-
- list( $prop_count ) = mysql_fetch_row( sql("SELECT COUNT(`port`) FROM `propositions`
- WHERE `port` = '1'
- AND `position` = '1' ", "setup->propositions"));
-
-
-
- // If there is more than one row for port=1 position=1
- if( $prop_count > 1 )
- {
- emergency("There are too many rows in the `propositions` table ");
- }
- elseif( $prop_count === '0' )
- {
- comment("Inserting the placeholders for the propositions ", 4);
-
- for( $port = 1; $port <= $S->ports; $port++ )
- {
- for( $position = 1; $position <= $S->positions; $position++ )
- {
- // Insert placeholder rows for all of the positions in all of the ports
- sql( "INSERT INTO `propositions` ( port, position )
- VALUES ('" . $port . "', '" . $position . "' ) ", "setup->tables" );
- }
- }
- }
- }
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- private function release_holds()
- {
- /*
- * CONCEPT:
- *
- * CAUTION:
- */
-
-
- // Clear the temporary holds (set when a new high value is reached)
- comment("Releasing all 'hold' stops. ", 6);
-
- sql("UPDATE `transactions` SET `stop` = '' WHERE `stop` = 'hold' ", "setup->release_holds");
-
- list( $count ) = mysql_fetch_row( sql("SELECT COUNT(`id`) FROM `transactions`
- WHERE `stop` = 'hold' ", "setup->release_holds"));
-
- // If there are still holds, emergency()
- if( $count )
- {
- emergency("[ $count ] rows have 'hold' stops ");
- }
-
- comment( "Done. ", 7 );
- }
-
-
-
- private function set_account_globals( $account_info )
- {
- /*
- * CONCEPT:
- *
- * CAUTION:
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Set the account globals to the account array defaults
- foreach( $account_info AS $setting => $value )
- {
- $S->$setting = $value;
- // comment("Setting \$S->$setting to [ $value ] from \$account_info", 4);
- }
-
- comment( "Done. ", 4 );
- }
-
-
-
- public function spirit()
- {
- /*
- * CONCEPT:
- * $setup->spirit setups up the correct class to be used as $spirit.
- *
- * CAUTION:
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
-
- // If the global conditions are OK and the orders are supposed to be sent to the broker . . .
- if( ( $S->spiritmode === 'demon' || $S->spiritmode === 'succubus' ) && !$S->satanrunning )
- {
- // Instantiate the broker interface class in demon.php
- $spirit = new demon();
- }
- elseif( $S->spiritmode === 'spirit' && $S->execute_transactions === 'yes' && $check->conditions() && !$S->satanrunning )
- {
- // Instantiate the broker interface class in spirit.php
- $spirit = new broker();
- }
- elseif( $S->satanrunning === 'yes' && $S->spiritmode === 'satan' )
- {
- // Instantiate the broker interface class in satan.php
- $spirit = new satan();
- }
-
- return $spirit;
- }
-
-
-
- private function tables()
- {
- /*
- * CONCEPT:
- * setup->tables() creates all of the tables needed to run jesus and god.
- *
- * CAUTION:
- * Make sure the tables are created correctly even when table correction is interupted due to a power
- * outage. Also, make sure that the tables are optimized to maximize the process speed.
- */
-
-
- // Include the static class that manages the global settings
- $S = settings::getInstance();
-
- // Instantiate the class that does all of the checking
- $check = new check();
-
- comment( "Creating the tables . . . ", 7 );
-
- // If the settings table is missing (check to create all of the tables)
- if( !$check->table( 'quotes' ) )
- {
- // Check to see if the transactions$port table has been created
- if( !$check->table( 'backtests' ) && $S->backtesting == 'yes' )
- {
- comment( "Creating the `backtests` table.", 5 );
-
- // Create the table that holds the test results
- sql( "CREATE TABLE IF NOT EXISTS `backtests` ( " .
- // id to make it easy to update test results
- "`id` int(10) unsigned NOT NULL auto_increment, " .
-
- // godprofit - setprofit = rank
- "`rank` int(10) DEFAULT NULL, " .
- // The percentage profit (or loss) between the startcash and godresult
- "`godprofit` int(11) NOT NULL DEFAULT '0', " .
- // The percentage profit (or loss) between the startcash and setresult
- "`setprofit` int(11) NOT NULL DEFAULT '0', " .
-
- // The place to store the failure message
- "`fail` text NOT NULL, " .
-
- // The total amount of cash the client puts in the brokerage account before god runs.
- "`startcash` decimal(10,2) NOT NULL DEFAULT '0.00', " .
- // The actual amount of money the position ended with
- "`godresult` decimal(10,2) NOT NULL DEFAULT '0.00', " .
-
- // startdate is the day the symbols are seleted on. The test process walks forward in time from startdate.
- "`startdate` date NOT NULL DEFAULT '0000-00-00', " .
- // The number of days between the startdate and the last day of trading
- "`duration` int(5) NOT NULL DEFAULT '0', " .
- // enddate is startdate + duration (days) (plus any extra time backtest needs to sell off all positions)
- "`enddate` date NOT NULL DEFAULT '0000-00-00', " .
-
- // The lowest price a symbol can be on the startdate
- "`startquote` decimal(10,2) NOT NULL DEFAULT '0.00', " .
-
- // The position number of the test result
- "`position` int(3) NOT NULL DEFAULT '0', " .
- // Internal variable that may affect results
- "`selldegree` int(3) NOT NULL DEFAULT '0', " .
-
- // The broker commission schedule used for the test
- "`broker` varchar(3) NOT NULL DEFAULT '', " .
- // Use R to select symbols
- "`select_r` varchar(3) NOT NULL DEFAULT '', " .
- // The set of symbols picked by R (based on their price correlation)
- "`symbols` text NOT NULL, " .
- // The diversify=yes forces god to avoid buying a symbol for more than one position
- "`diversify` varchar(3) NOT NULL DEFAULT '', " .
-
- // The hold=yes temporarily prevents god from selling a symbol with a rising price
- "`hold` varchar(3) NOT NULL DEFAULT '', " .
- // The number of positions processed during the test
- "`positions` int(3) NOT NULL DEFAULT '0', " .
- // The number of symbols selected for the set
- "`quantity` int(3) NOT NULL DEFAULT '0', " .
- // The sharebuffer setting god uses solely
- "`sharebuffer` int(11) NOT NULL DEFAULT '0', " .
- // The number of transactions that god executed
- "`transactions` int(11) NOT NULL DEFAULT '0', " .
-
- // The max amount of overall profit before triggering a stop
- "`profitlimitpercent` int(3) NOT NULL DEFAULT '0', " .
- // The max amount of overall loss before triggering a stop
- "`stoplosspercentage` int(3) NOT NULL DEFAULT '0', " .
- // The max percentage profit after buying a symbol before triggering a stop
- "`buystop_percentage` int(3) NOT NULL DEFAULT '0', " .
- // The max amount of loss after buying a symbol before triggering a stop
- "`sellstoppercentage` int(3) NOT NULL DEFAULT '0', " .
- // The max amount of loss from a high price before triggering a stop
- "`trailingpercentage` int(3) NOT NULL DEFAULT '0', " .
- // The percentage of slippage before triggering a stop
- "`pricebufferpercent` int(3) NOT NULL DEFAULT '0', " .
-
- // Setting KEYS increased performance
- "KEY `id` (`id`), " .
-
- "KEY `rank` (`rank`), " .
- "KEY `godprofit` (`godprofit`), " .
- "KEY `setprofit` (`setprofit`), " .
-
- "KEY `startcash` (`startcash`), " .
- "KEY `godresult` (`godresult`), " .
-
- // fail key not needed
-
- // startdate key not needed
- "KEY `startquote` (`startquote`), " .
-
- "KEY `position` (`position`), " .
- "KEY `selldegree` (`selldegree`), " .
-
- "KEY `broker` (`broker`), " .
- "KEY `select_r` (`select_r`), " .
- // symbols key not needed
- "KEY `diversify` (`diversify`), " .
-
- "KEY `duration` (`duration`), " .
- // enddate key not needed
-
- "KEY `hold` (`hold`), " .
- "KEY `positions` (`positions`), " .
- "KEY `quantity` (`quantity`), " .
- "KEY `sharebuffer` (`sharebuffer`), " .
- "KEY `transactions` (`transactions`), " .
-
- "KEY `profitlimitpercent` (`profitlimitpercent`), " .
- "KEY `stoplosspercentage` (`stoplosspercentage`), " .
- "KEY `buystop_percentage` (`buystop_percentage`), " .
- "KEY `sellstoppercentage` (`sellstoppercentage`), " .
- "KEY `trailingpercentage` (`trailingpercentage`), " .
- "KEY `pricebufferpercent` (`pricebufferpercent`) ) ENGINE=InnoDB ", "setup->tables" );
- }
-
- // If the jesusoptions table is missing, create it
- if( !$check->table( 'messages' ) )
- {
- comment( "Creating the `messages` table.", 5 );
-
- // Create a jesusoptions master table
- sql( "CREATE TABLE IF NOT EXISTS `messages` (
- `fullname` varchar(100) NOT NULL,
- `database` varchar(100) NOT NULL,
- `port` int(10) NOT NULL,
- `source` varchar(100) NOT NULL,
- `error_type` varchar(100) NOT NULL,
- `message` varchar(200) NOT NULL,
- `timestamp` datetime NOT NULL )
- ENGINE=InnoDB ", 'setup->tables' );
- }
-
- // Create the propsositions table if it does not exist
- if( !$check->table( 'propositions' ) )
- {
- comment( "Creating the `propositions` table.", 5 );
-
- sql( "CREATE TABLE `propositions`
- (`port` int(11) NOT NULL,
- `position` int(11) NOT NULL,
- `buydegree` int(11) NOT NULL DEFAULT 0,
- `selldegree` int(11) NOT NULL DEFAULT 0,
- `transid` int(11) NOT NULL DEFAULT 0,
- `cash_value` double (8,2) NOT NULL DEFAULT 0,
- `shares_value` double (8,2) NOT NULL DEFAULT 0,
- `original_value` double (8,2) NOT NULL DEFAULT 0,
- `high_position` double (8,2) NOT NULL DEFAULT 0,
- `starting_value` double (8,2) NOT NULL DEFAULT 0,
- `high` double (8,2) NOT NULL DEFAULT 0,
- KEY `original_value` (`port`, `position`,`transid`) )
- ENGINE=InnoDB ", "setup->tables" );
-
- // Set a flag for setup->propositions()
- $this->setup_propositions = 'yes';
- }
-
- // If the quotes table is missing, create it
- if( !$check->table( 'quotes' ) )
- {
- comment( "Creating the `quotes` table.", 5 );
-
- sql( "CREATE TABLE `quotes`
- (`symbol` char(8) NOT NULL,
- `price` double (8,2) DEFAULT 0 NOT NULL,
- `port` tinyint(3) NOT NULL,
- `buy` char(2) DEFAULT 'N' NOT NULL,
- date datetime DEFAULT '1.1.0 0:0:0' NOT NULL,
- PRIMARY KEY (`symbol`,`port`,`date`),
- UNIQUE KEY `symbol` (`symbol`) )
- ENGINE=InnoDB ", "setup->tables" );
-
- $S->setup_quotes = 'yes';
- }
-
- // Check to make surethere is a quoteshistory table
- if( !$check->table( 'quoteshistory' ) )
- {
- comment( "Creating the quoteshistory table.", 5 );
-
- sql( "CREATE TABLE `quoteshistory`
- (`symbol` char(8) NOT NULL,
- `price` double (8,2) NOT NULL,
- `port` tinyint(3) NOT NULL,
- `date` datetime NOT NULL)
- ENGINE=InnoDB ", "setup->tables" );
- }
-
- // Check to make surethere is a quoteshistory table
- if( !$check->table( 'replacements' ) )
- {
- comment( "Creating the replacements table.", 5 );
-
- sql( "CREATE TABLE `replacements`
- (`from_symbol` char(8) NOT NULL,
- `to_symbol` char(8) NOT NULL,
- `change_date` datetime NOT NULL,
- `completed` char(1) DEFAULT 'N' NOT NULL )
- ENGINE=InnoDB ", "setup->tables" );
- }
-
- // Check to make sure there is a selecta table
- if( !$check->table( 'selecta' ) )
- {
- comment( "Creating the selecta table.", 5 );
-
- sql("CREATE TABLE `selecta` (
- `date` date NOT NULL,
- `name1` text NOT NULL,
- `name2` text NOT NULL,
- `crosses` text NOT NULL,
- `crossprob` text NOT NULL )
- ENGINE=InnoDB ", "setup->tables" );
- }
-
- // Create the `settings` table if it does not exist
- if( !$check->table( 'settings' ) )
- {
- comment( "Creating the `settings` table.", 5 );
-
- // Create the `settings` table
- sql( "CREATE TABLE `settings`
- (name char(24) NOT NULL,
- port int(3) NOT NULL,
- value char(64) NOT NULL,
- KEY `name` (`name`, `port`),
- KEY `port` (`port`,`name`) )
- ENGINE=InnoDB ", 'setup->tables' );
-
- // Set a flag for setup->insert_settings()
- $this->setup_settings = 'yes';
- }
-
- // Check to see if the transactions$port table has been created
- if( !$check->table( 'skippedtrans' ) )
- {
- comment( "Creating the `skippedtrans` table.", 5 );
-
- sql( "CREATE TABLE skippedtrans(
- transid int unsigned NOT NULL, PRIMARY KEY (transid),
- symbol char(8) NOT NULL,
- t_type enum('buy','sell') NOT NULL,
- port tinyint(3) NOT NULL,
- position tinyint(3) unsigned NOT NULL,
- shares int unsigned NOT NULL,
- price double (8,2) NOT NULL,
- high double (8,2) NOT NULL,
- cost double (8,2) NOT NULL,
- credit double (8,2) NOT NULL,
- stop char(15) NOT NULL,
- t_date datetime NOT NULL, KEY (t_date),
- completed char(1) NOT NULL,
- pricebuffer double (8,2) NOT NULL )
- ENGINE=InnoDB ", 'setup->tables' );
- }
-
- // Check to see if the transactions$port table has been created
- if( !$check->table( 'startdates' ) && $S->backtesting == 'yes' )
- {
- comment( "Creating the `startdates` table.", 5 );
-
- sql( "CREATE TABLE `startdates` (
- `id` int(10) unsigned NOT NULL auto_increment,
- `startdate` datetime NOT NULL,
- PRIMARY KEY (`id`),
- KEY `position` (`startdate`,`id`) )
- ENGINE=InnoDB ", "setup->tables" );
- }
-
- // Check to see if the subtransactions table exists
- if( !$check->table( 'subtransactions' ) )
- {
- comment( "Creating the `subtransactions` table.", 5 );
-
- sql( "CREATE TABLE `subtransactions` (
- `id` int(10) unsigned NOT NULL auto_increment,
- `transid` int(11) NOT NULL default '0',
- `orderid` varchar(100) NOT NULL default '',
- `symbol` char(8) NOT NULL default '',
- `t_type` enum('buy','sell') NOT NULL default 'buy',
- `position` int(10) unsigned NOT NULL default '0',
- `shares` int(10) unsigned NOT NULL default '0',
- `price` double (8,2) NOT NULL default '0',
- `feesaver` char(1) NOT NULL default '',
- t_date datetime NOT NULL, KEY (t_date),
- `pricebuffer` double (8,2) NOT NULL default '0',
- PRIMARY KEY (`id`),
- KEY `position` (`position`,`id`) )
- ENGINE=InnoDB ", 'setup->tables' );
- }
-
- // Check to see if the transactions$port table has been created
- if( !$check->table( 'transactions' ) )
- {
- comment( "Creating the `transactions` table.", 5 );
-
- sql( "CREATE TABLE transactions(
- `id` int(10) unsigned NOT NULL auto_increment,
- `symbol` char(8) NOT NULL,
- `t_type` enum('buy','sell') NOT NULL,
- `port` int(3) unsigned NOT NULL,
- `position` int unsigned NOT NULL,
- `shares` int(10) unsigned NOT NULL default '0',
- `price` double (8,2) NOT NULL default '0',
- `cost` double (8,2) NOT NULL,
- `credit` double (8,2) NOT NULL,
- `stop` char(15) NOT NULL,
- `t_date` datetime NOT NULL, KEY (t_date),
- `completed` char(1) NOT NULL,
- `pricebuffer` double (8,2) NOT NULL default '0',
- `value` double (8,2) NOT NULL default '0',
- PRIMARY KEY (`id`),
- KEY `port` (`port`, `id`, `position`),
- KEY `position` (`position`,`id`,`port`) )
- ENGINE=InnoDB ", 'setup->tables' );
- }
- }
-
- comment( "Done.", 7 );
- }
-
-
-
- }
-
- ?>