Merge pull request #526 from danielyxie/stock-market-shares-limit

Stock market shares limit
This commit is contained in:
danielyxie 2019-01-09 02:31:20 -08:00 committed by GitHub
commit d5a2b9e0a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 172342 additions and 326 deletions

@ -537,70 +537,3 @@
display: inline;
width: 25%;
}
/* Stock market */
#stock-market-container {
position: fixed;
padding: 6px;
p {
font-size: $defaultFontSize * 0.8125;
}
a {
font-size: $defaultFontSize * 0.875;
}
h2 {
margin-top: 10px;
margin-left: 10px;
display: block;
}
}
/* Change font size of Stock TIcker headers */
#stock-market-list li {
button {
font-size: $defaultFontSize;
}
}
#stock-market-container p {
padding: 10px;
margin: 10px;
width: 70%;
}
#stock-market-container a {
margin: 10px;
}
#stock-market-watchlist-filter {
width: 50%;
margin-left: 10px;
}
.stock-market-input {
display: inline-block;
padding: 4px;
margin: 2px;
background-color: #000;
border: 1px solid #fff;
color: var(--my-font-color);
}
.stock-market-position-text {
color: #fff;
display: inline-block;
}
.stock-market-order-list {
overflow-y: auto;
max-height: 100px;
}
.stock-market-order-cancel-btn {
background-color: #000;
border: 1px solid #fff;
color: var(--my-font-color);
margin: 2px;
padding: 0;
}

66
css/stockmarket.scss Normal file

@ -0,0 +1,66 @@
@import "theme";
#stock-market-container {
position: fixed;
padding: 6px;
p {
font-size: $defaultFontSize * 0.8125;
}
a {
font-size: $defaultFontSize * 0.875;
}
h2 {
margin-top: 10px;
margin-left: 10px;
display: block;
}
}
#stock-market-list li {
button {
font-size: $defaultFontSize;
}
}
#stock-market-container p {
padding: 6px;
margin: 6px;
width: 70%;
}
#stock-market-container a {
margin: 10px;
}
#stock-market-watchlist-filter {
width: 50%;
margin-left: 10px;
}
.stock-market-input {
display: inline-block;
padding: 4px;
margin: 2px;
background-color: #000;
border: 1px solid #fff;
color: var(--my-font-color);
}
.stock-market-position-text {
color: #fff;
display: inline-block;
}
.stock-market-order-list {
overflow-y: auto;
max-height: 100px;
}
.stock-market-order-cancel-btn {
background-color: #000;
border: 1px solid #fff;
color: var(--my-font-color);
margin: 2px;
padding: 0;
}

61149
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

8
dist/engine.css vendored

@ -1222,7 +1222,8 @@ button {
display: inline;
width: 25%; }
/* Stock market */
/* COLORS */
/* Attributes */
#stock-market-container {
position: fixed;
padding: 6px; }
@ -1235,13 +1236,12 @@ button {
margin-left: 10px;
display: block; }
/* Change font size of Stock TIcker headers */
#stock-market-list li button {
font-size: 16px; }
#stock-market-container p {
padding: 10px;
margin: 10px;
padding: 6px;
margin: 6px;
width: 70%; }
#stock-market-container a {

111104
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -3,7 +3,8 @@ Netscript Trade Information eXchange (TIX) API
The Trade Information eXchange (TIX) is the communications protocol supported by the World Stock Exchange (WSE).
The WSE provides an API that allows you to automatically communicate with the
`Stock Market <http://bitburner.wikia.com/wiki/Stock_Market>`_. This API lets you write code using Netscript
:ref:`Stock Market <gameplay_stock_market>`.
This API lets you write code using Netscript
to build automated trading systems and create your own algorithmic trading strategies. Access to this
TIX API can be purchased by visiting the World Stock Exchange in-game.
@ -62,6 +63,19 @@ getStockPosition
sharesShort = pos[2];
avgPxShort = pos[3];
getStockMaxShares
-----------------
.. js:function:: getStockMaxShares(sym)
:param string sym: Stock symbol
:RAM cost: 2 GB
Returns the maximum number of shares that the stock has. This is the maximum
amount of the stock that can be purchased in both the Long and Short
positions combined
buyStock
--------

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bitburner</title>
<title>Bitburner - development</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -112,7 +112,7 @@
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1"/>
<input id="script-editor-filename" type="text" maxlength="30" tabindex="1" />
</div>
<div id="javascript-editor"></div>
@ -162,7 +162,7 @@
<fieldset>
<label for="script-editor-option-maxerr" class="tooltip">Max Error Count</label>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr"/>
<input type="range" max="1000" min="50" value="200" step="1" name="script-editor-option-maxerr" id="script-editor-option-maxerr" />
<em id="script-editor-option-maxerror-value-label" style="font-style: normal;"></em>
</fieldset>
</div> <!-- End script editor options panel -->
@ -173,7 +173,7 @@
<table id="terminal">
<tr id="terminal-input">
<td id="terminal-input-td" tabindex="2">$
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/>
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
</td>
</tr>
</table>
@ -190,7 +190,7 @@
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p>
<p id="active-scripts-total-prod">Total online production of
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
@ -204,19 +204,19 @@
The Hacknet is a global, decentralized network of machines. It is used by hackers all around
the world to anonymously share computing power and perform distributed cyberattacks without the
fear of being traced.
<br/><br/>
<br /><br />
Here, you can purchase a Hacknet Node, a specialized machine that can connect and contribute its
resources to the Hacknet network. This allows you to take a small percentage of profits
from hacks performed on the network. Essentially, you are renting out your Node's computing power.
<br/><br/>
<br /><br />
Each Hacknet Node you purchase will passively earn you money. Each Hacknet Node can be upgraded
in order to increase its computing power and thereby increase the profit you earn from it.
</p>
<a id="hacknet-nodes-purchase-button" class="a-link-button"> Purchase Hacknet Node </a>
<br/>
<br />
<div id="hacknet-nodes-money-multipliers-div">
<p id="hacknet-nodes-money">
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br/>
<span>Money:</span><span id="hacknet-nodes-player-money" class="money-gold"></span><br />
<span>Total Hacknet Node Production:</span><span id="hacknet-nodes-total-production" class="money-gold"></span>
</p>
<span id="hacknet-nodes-multipliers">
@ -474,7 +474,8 @@
<!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container">
<a id="tutorial-getting-started-link" class="a-link-button" href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-getting-started-link" class="a-link-button"
href="http://bitburner.wikia.com/wiki/Chapt3rs_Guide_to_Getting_Started_with_Bitburner" target="_blank"> Getting Started </a>
<a id="tutorial-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </a>
@ -483,7 +484,8 @@
<a id="tutorial-jobs-link" class="a-link-button"> Companies and Infiltration </a>
<a id="tutorial-factions-link" class="a-link-button"> Factions </a>
<a id="tutorial-augmentations-link" class="a-link-button"> Augmentations </a>
<a id="tutorial-shortcuts-link" class="a-link-button" href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-shortcuts-link" class="a-link-button"
href="https://bitburner.wikia.com/wiki/Shortcuts" target="_blank"> Keyboard Shortcuts </a>
<a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p>
@ -574,7 +576,7 @@
<p id="location-slums-description">
You have entered the Slums, a poverty-ridden district filled with gangs, criminals, and
other shadowy entities. The city's government and police have neglected this area for years...
<br/><br/><br/>
<br /><br /><br />
In the Slums, you can commit crimes to earn money and experience. Crime attempts are not always
successful. Your chance at successfully committing a crime is determined by your stats.
</p>
@ -621,7 +623,7 @@
<div id="stock-market-container" class="generic-menupage-container">
<p>
Welcome to the World Stock Exchange (WSE)! <br/><br/>
Welcome to the World Stock Exchange (WSE)! <br /><br />
To begin trading, you must first purchase an account. WSE accounts will persist
after you 'reset' by installing Augmentations.
@ -634,7 +636,7 @@
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
Purchasing access to the TIX API lets you write code to create your own algorithmic/automated
trading strategies.
<br/><br/>
<br /><br />
If you purchase access to the TIX API, you will retain that access even after
you 'reset' by installing Augmentations.
</p>
@ -644,7 +646,7 @@
<p>
Four Sigma's (4S) Market Data Feed provides information about stocks
that will help your trading strategies.
<br/><br/>
<br /><br />
If you purchase access to 4S Market Data and/or the 4S TIX API, you will
retain that access even after you 'reset' by installing Augmentations.
</p>
@ -662,7 +664,7 @@
<a id="stock-market-mode" class="a-link-button tooltip"></a>
<a id="stock-market-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
<br/><br/>
<br /><br />
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"/>
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
<ul id="stock-market-list" style="list-style:none;">
@ -692,7 +694,7 @@
<div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"> </p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<button id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </button>
<button id="yes-no-text-input-box-no" class="popup-box-button"> No </button>
</div>
@ -704,7 +706,7 @@
<p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning">
Would you like to join? <br/> <br/>
Would you like to join? <br /> <br />
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button>
@ -717,8 +719,8 @@
<div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br/><br/>
<select id="infiltration-faction-select"> </select> <br/>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br /><br />
<select id="infiltration-faction-select"> </select> <br />
<button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button>
</div>
@ -804,7 +806,7 @@
<div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button>
<h1> Game Options </h1>
<br/>
<br />
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
@ -816,7 +818,7 @@
</span>
</label>
<input type="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/>
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -830,7 +832,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -844,7 +846,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -856,7 +858,7 @@
</span>
</label>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
</fieldset>
@ -968,7 +970,7 @@
<button id="save-game-link" class="a-link-button"> Save Game </button>
<button id="delete-game-link" class="a-link-button"> Delete Game </button>
<button id="export-game-link" class="a-link-button"> Export Game </button>
<input type="file" id="import-game-file-selector" name="file"/>
<input type="file" id="import-game-file-selector" name="file" />
<button id="import-game-link" class="a-link-button"> Import Game </button>
<button id="copy-save-to-clipboard-link" class="std-button">
Copy Save data to Clipboard

@ -6,8 +6,8 @@ import { Player } from "./Player";
import { AllServers } from "./Server";
import { hackWorldDaemon } from "./RedPill";
import { StockMarket,
SymbolToStockMap } from "./StockMarket";
import { Stock } from "./Stock";
SymbolToStockMap } from "./StockMarket/StockMarket";
import { Stock } from "./StockMarket/Stock";
import { Terminal } from "./Terminal";
import { numeralWrapper } from "./ui/numeralFormat";
import { dialogBoxCreate } from "../utils/DialogBox";

@ -40,12 +40,12 @@ import {Server, getServer, AddToAllServers,
GetServerByHostname, numCycleForGrowth} from "./Server";
import {Settings} from "./Settings";
import {SpecialServerIps} from "./SpecialServerIps";
import {Stock} from "./Stock";
import {Stock} from "./StockMarket/Stock";
import {StockMarket, StockSymbols, SymbolToStockMap,
initStockMarket, initSymbolToStockMap, buyStock,
sellStock, updateStockPlayerPosition,
shortStock, sellShort, OrderTypes,
PositionTypes, placeOrder, cancelOrder} from "./StockMarket";
PositionTypes, placeOrder, cancelOrder} from "./StockMarket/StockMarket";
import {post} from "./ui/postToTerminal";
import {TextFile, getTextFile, createTextFile} from "./TextFile";
@ -1537,6 +1537,22 @@ function NetscriptFunctions(workerScript) {
}
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
},
getStockMaxShares : function(symbol) {
if (workerScript.checkingRam) {
return updateStaticRam("getStockMaxShares", CONSTANTS.ScriptGetStockRamCost);
}
updateDynamicRam("getStockMaxShares", CONSTANTS.ScriptGetStockRamCost);
if (!Player.hasTixApiAccess) {
throw makeRuntimeRejectMsg(workerScript, "You don't have TIX API Access! Cannot use getStockMaxShares()");
}
const stock = SymbolToStockMap[symbol];
if (stock == null) {
throw makeRuntimeRejectMsg(workerScript, "Invalid stock symbol passed into getStockMaxShares()");
}
return stock.maxShares;
},
buyStock : function(symbol, shares) {
if (workerScript.checkingRam) {
return updateStaticRam("buyStock", CONSTANTS.ScriptBuySellStockRamCost);
@ -1556,6 +1572,7 @@ function NetscriptFunctions(workerScript) {
shares = Math.round(shares);
if (shares === 0) {return 0;}
// Does player have enough money?
var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
workerScript.scriptRef.log("Not enough money to purchase " + formatNumber(shares, 0) + " shares of " +
@ -1564,6 +1581,13 @@ function NetscriptFunctions(workerScript) {
return 0;
}
// Would this purchase exceed the maximum number of shares?
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
workerScript.scriptRef.log(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ` +
`${stock.maxShares} shares.`);
return 0;
}
var origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice;

@ -29,7 +29,7 @@ import {SpecialServerIps, SpecialServerIpsMap,
SpecialServerNames} from "./SpecialServerIps";
import {initStockMarket, initSymbolToStockMap,
stockMarketContentCreated,
setStockMarketContentCreated} from "./StockMarket";
setStockMarketContentCreated} from "./StockMarket/StockMarket";
import {Terminal, postNetburnerText} from "./Terminal";
import Decimal from "decimal.js";
import {dialogBoxCreate} from "../utils/DialogBox";

@ -16,7 +16,7 @@ import {loadAllRunningScripts} from "./Script";
import {AllServers, loadAllServers} from "./Server";
import {Settings} from "./Settings";
import {loadSpecialServerIps, SpecialServerIps} from "./SpecialServerIps";
import {loadStockMarket, StockMarket} from "./StockMarket";
import {loadStockMarket, StockMarket} from "./StockMarket/StockMarket";
import {dialogBoxCreate} from "../utils/DialogBox";
import {gameOptionsBoxClose} from "../utils/GameOptions";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";

@ -1,5 +1,5 @@
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
import { getRandomInt } from "../utils/helpers/getRandomInt";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { getRandomInt } from "../../utils/helpers/getRandomInt";
/**
* Represents the valuation of a company in the World Stock Exchange.
@ -22,6 +22,11 @@ export class Stock {
*/
readonly cap: number;
/**
* Maximum number of shares that player can own (both long and short combined)
*/
readonly maxShares: number;
/**
* Maximum volatility
*/
@ -78,7 +83,8 @@ export class Stock {
mv: number = 1,
b: boolean = true,
otlkMag: number = 0,
initPrice: number = 10e3) {
initPrice: number = 10e3,
marketCap: number = 1e12) {
this.name = name;
this.symbol = symbol;
this.price = initPrice;
@ -91,6 +97,10 @@ export class Stock {
this.otlkMag = otlkMag;
this.cap = getRandomInt(initPrice * 1e3, initPrice * 25e3);
// Maximum shares is determined by market cap, and is rounded to nearest millions
let maxSharesUnrounded: number = (marketCap / initPrice);
this.maxShares = Math.round(maxSharesUnrounded / 1e6) * 1e6;
this.posTxtEl = null;
}

145
src/StockMarket.js → src/StockMarket/StockMarket.js Executable file → Normal file

@ -1,27 +1,29 @@
import {CONSTANTS} from "./Constants";
import {Locations} from "./Locations";
import {hasWallStreetSF, wallStreetSFLvl} from "./NetscriptFunctions";
import {WorkerScript} from "./NetscriptWorker";
import {Player} from "./Player";
import {Stock} from "./Stock";
import {dialogBoxCreate} from "../utils/DialogBox";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners";
import {CONSTANTS} from "../Constants";
import {Locations} from "../Locations";
import {hasWallStreetSF, wallStreetSFLvl} from "../NetscriptFunctions";
import {WorkerScript} from "../NetscriptWorker";
import {Player} from "../Player";
import {Page, routing} from ".././ui/navigationTracking";
import {numeralWrapper} from ".././ui/numeralFormat";
import {dialogBoxCreate} from "../../utils/DialogBox";
import {clearEventListeners} from "../../utils/uiHelpers/clearEventListeners";
import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver";
import {Page, routing} from "./ui/navigationTracking";
import {numeralWrapper} from "./ui/numeralFormat";
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
import {getRandomInt} from "../utils/helpers/getRandomInt";
import {KEY} from "../utils/helpers/keyCodes";
import {createElement} from "../utils/uiHelpers/createElement";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById";
Generic_fromJSON} from "../../utils/JSONReviver";
import {exceptionAlert} from "../../utils/helpers/exceptionAlert";
import {getRandomInt} from "../../utils/helpers/getRandomInt";
import {KEY} from "../../utils/helpers/keyCodes";
import {createElement} from "../../utils/uiHelpers/createElement";
import {removeChildrenFromElement} from "../../utils/uiHelpers/removeChildrenFromElement";
import {removeElementById} from "../../utils/uiHelpers/removeElementById";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox";
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../../utils/YesNoBox";
var OrderTypes = {
LimitBuy: "Limit Buy Order",
@ -228,135 +230,135 @@ function initStockMarket() {
const randInt = getRandomInt;
var ecorp = Locations.AevumECorp;
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], randInt(40, 50) / 100, true, 19, randInt(17e3, 28e3));
var ecorpStk = new Stock(ecorp, StockSymbols[ecorp], randInt(40, 50) / 100, true, 19, randInt(17e3, 28e3), 3e12);
StockMarket[ecorp] = ecorpStk;
var megacorp = Locations.Sector12MegaCorp;
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], randInt(40,50)/100, true, 19, randInt(24e3, 34e3));
var megacorpStk = new Stock(megacorp, StockSymbols[megacorp], randInt(40,50)/100, true, 19, randInt(24e3, 34e3), 3e12);
StockMarket[megacorp] = megacorpStk;
var blade = Locations.Sector12BladeIndustries;
var bladeStk = new Stock(blade, StockSymbols[blade], randInt(70, 80)/100, true, 13, randInt(12e3, 25e3));
var bladeStk = new Stock(blade, StockSymbols[blade], randInt(70, 80)/100, true, 13, randInt(12e3, 25e3), 1.9e12);
StockMarket[blade] = bladeStk;
var clarke = Locations.AevumClarkeIncorporated;
var clarkeStk = new Stock(clarke, StockSymbols[clarke], randInt(65, 75)/100, true, 12, randInt(10e3, 25e3));
var clarkeStk = new Stock(clarke, StockSymbols[clarke], randInt(65, 75)/100, true, 12, randInt(10e3, 25e3), 1.8e12);
StockMarket[clarke] = clarkeStk;
var omnitek = Locations.VolhavenOmniTekIncorporated;
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], randInt(60, 70)/100, true, 12, randInt(32e3, 43e3));
var omnitekStk = new Stock(omnitek, StockSymbols[omnitek], randInt(60, 70)/100, true, 12, randInt(32e3, 43e3), 2.1e12);
StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma;
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], randInt(100, 110)/100, true, 17, randInt(50e3, 80e3));
var foursigmaStk = new Stock(foursigma, StockSymbols[foursigma], randInt(100, 110)/100, true, 17, randInt(50e3, 80e3), 2.4e12);
StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational;
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], randInt(75, 85)/100, true, 10, randInt(16e3, 28e3));
var kuaigongStk = new Stock(kuaigong, StockSymbols[kuaigong], randInt(75, 85)/100, true, 10, randInt(16e3, 28e3), 2.3e12);
StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies;
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], randInt(120, 130)/100, true, 16, randInt(29e3, 36e3));
var fulcrumStk = new Stock(fulcrum, StockSymbols[fulcrum], randInt(120, 130)/100, true, 16, randInt(29e3, 36e3), 2.4e12);
StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies;
var stormStk = new Stock(storm, StockSymbols[storm], randInt(80, 90)/100, true, 7, randInt(20e3, 25e3));
var stormStk = new Stock(storm, StockSymbols[storm], randInt(80, 90)/100, true, 7, randInt(20e3, 25e3), 1.2e12);
StockMarket[storm] = stormStk;
var defcomm = Locations.NewTokyoDefComm;
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], randInt(60, 70)/100, true, 10, randInt(6e3, 19e3));
var defcommStk = new Stock(defcomm, StockSymbols[defcomm], randInt(60, 70)/100, true, 10, randInt(6e3, 19e3), 900e9);
StockMarket[defcomm] = defcommStk;
var helios = Locations.VolhavenHeliosLabs;
var heliosStk = new Stock(helios, StockSymbols[helios], randInt(55, 65)/100, true, 9, randInt(10e3, 18e3));
var heliosStk = new Stock(helios, StockSymbols[helios], randInt(55, 65)/100, true, 9, randInt(10e3, 18e3), 825e9);
StockMarket[helios] = heliosStk;
var vitalife = Locations.NewTokyoVitaLife;
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], randInt(70, 80)/100, true, 7, randInt(8e3, 14e3));
var vitalifeStk = new Stock(vitalife, StockSymbols[vitalife], randInt(70, 80)/100, true, 7, randInt(8e3, 14e3), 1e12);
StockMarket[vitalife] = vitalifeStk;
var icarus = Locations.Sector12IcarusMicrosystems;
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3));
var icarusStk = new Stock(icarus, StockSymbols[icarus], randInt(60, 70)/100, true, 7.5, randInt(12e3, 24e3), 800e12);
StockMarket[icarus] = icarusStk;
var universalenergy = Locations.Sector12UniversalEnergy;
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], randInt(50, 60)/100, true, 10, randInt(16e3, 29e3));
var universalenergyStk = new Stock(universalenergy, StockSymbols[universalenergy], randInt(50, 60)/100, true, 10, randInt(16e3, 29e3), 900e9);
StockMarket[universalenergy] = universalenergyStk;
var aerocorp = Locations.AevumAeroCorp;
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], randInt(55, 65)/100, true, 6, randInt(8e3, 17e3));
var aerocorpStk = new Stock(aerocorp, StockSymbols[aerocorp], randInt(55, 65)/100, true, 6, randInt(8e3, 17e3), 640e9);
StockMarket[aerocorp] = aerocorpStk;
var omnia = Locations.VolhavenOmniaCybersystems;
var omniaStk = new Stock(omnia, StockSymbols[omnia], randInt(65, 75)/100, true, 4.5, randInt(6e3, 15e3));
var omniaStk = new Stock(omnia, StockSymbols[omnia], randInt(65, 75)/100, true, 4.5, randInt(6e3, 15e3), 600e9);
StockMarket[omnia] = omniaStk;
var solaris = Locations.ChongqingSolarisSpaceSystems;
var solarisStk = new Stock(solaris, StockSymbols[solaris], randInt(70, 80)/100, true, 8.5, randInt(14e3, 28e3));
var solarisStk = new Stock(solaris, StockSymbols[solaris], randInt(70, 80)/100, true, 8.5, randInt(14e3, 28e3), 705e9);
StockMarket[solaris] = solarisStk;
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals;
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], randInt(55, 65)/100, true, 10.5, randInt(12e3, 30e3));
var globalpharmStk = new Stock(globalpharm, StockSymbols[globalpharm], randInt(55, 65)/100, true, 10.5, randInt(12e3, 30e3), 695e9);
StockMarket[globalpharm] = globalpharmStk;
var nova = Locations.IshimaNovaMedical;
var novaStk = new Stock(nova, StockSymbols[nova], randInt(70, 80)/100, true, 5, randInt(15e3, 27e3));
var novaStk = new Stock(nova, StockSymbols[nova], randInt(70, 80)/100, true, 5, randInt(15e3, 27e3), 600e9);
StockMarket[nova] = novaStk;
var watchdog = Locations.AevumWatchdogSecurity;
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], randInt(240, 260)/100, true, 1.5, randInt(4e3, 8.5e3));
var watchdogStk = new Stock(watchdog, StockSymbols[watchdog], randInt(240, 260)/100, true, 1.5, randInt(4e3, 8.5e3), 450e9);
StockMarket[watchdog] = watchdogStk;
var lexocorp = Locations.VolhavenLexoCorp;
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], randInt(115, 135)/100, true, 6, randInt(4.5e3, 8e3));
var lexocorpStk = new Stock(lexocorp, StockSymbols[lexocorp], randInt(115, 135)/100, true, 6, randInt(4.5e3, 8e3), 300e9);
StockMarket[lexocorp] = lexocorpStk;
var rho = Locations.AevumRhoConstruction;
var rhoStk = new Stock(rho, StockSymbols[rho], randInt(50, 70)/100, true, 1, randInt(2e3, 7e3));
var rhoStk = new Stock(rho, StockSymbols[rho], randInt(50, 70)/100, true, 1, randInt(2e3, 7e3), 180e9);
StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises;
var alphaStk = new Stock(alpha, StockSymbols[alpha], randInt(175, 205)/100, true, 10, randInt(4e3, 8.5e3));
var alphaStk = new Stock(alpha, StockSymbols[alpha], randInt(175, 205)/100, true, 10, randInt(4e3, 8.5e3), 240e9);
StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities;
var syscoreStk = new Stock(syscore, StockSymbols[syscore], randInt(150, 170)/100, true, 3, randInt(3e3, 8e3));
var syscoreStk = new Stock(syscore, StockSymbols[syscore], randInt(150, 170)/100, true, 3, randInt(3e3, 8e3), 200e9);
StockMarket[syscore] = syscoreStk;
var computek = Locations.VolhavenCompuTek;
var computekStk = new Stock(computek, StockSymbols[computek], randInt(80, 100)/100, true, 4, randInt(1e3, 6e3));
var computekStk = new Stock(computek, StockSymbols[computek], randInt(80, 100)/100, true, 4, randInt(1e3, 6e3), 185e9);
StockMarket[computek] = computekStk;
var netlink = Locations.AevumNetLinkTechnologies;
var netlinkStk = new Stock(netlink, StockSymbols[netlink], randInt(400, 430)/100, true, 1, randInt(1e3, 5e3));
var netlinkStk = new Stock(netlink, StockSymbols[netlink], randInt(400, 430)/100, true, 1, randInt(1e3, 5e3), 58e9);
StockMarket[netlink] = netlinkStk;
var omega = Locations.IshimaOmegaSoftware;
var omegaStk = new Stock(omega, StockSymbols[omega], randInt(90, 110)/100, true, 0.5, randInt(1e3, 8e3));
var omegaStk = new Stock(omega, StockSymbols[omega], randInt(90, 110)/100, true, 0.5, randInt(1e3, 8e3), 60e9);
StockMarket[omega] = omegaStk;
var fns = Locations.Sector12FoodNStuff;
var fnsStk = new Stock(fns, StockSymbols[fns], randInt(70, 80)/100, false, 1, randInt(500, 4.5e3));
var fnsStk = new Stock(fns, StockSymbols[fns], randInt(70, 80)/100, false, 1, randInt(500, 4.5e3), 45e9);
StockMarket[fns] = fnsStk;
var sigmacosm = "Sigma Cosmetics";
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], randInt(260, 300)/100, true, 0, randInt(1.5e3, 3.5e3));
var sigmacosmStk = new Stock(sigmacosm, StockSymbols[sigmacosm], randInt(260, 300)/100, true, 0, randInt(1.5e3, 3.5e3), 30e9);
StockMarket[sigmacosm] = sigmacosmStk;
var joesguns = "Joes Guns";
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], randInt(360, 400)/100, true, 1, randInt(250, 1.5e3));
var joesgunsStk = new Stock(joesguns, StockSymbols[joesguns], randInt(360, 400)/100, true, 1, randInt(250, 1.5e3), 42e9);
StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures";
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], randInt(120, 175)/100, true, 13.5, randInt(250, 1.5e3));
var catalystStk = new Stock(catalyst, StockSymbols[catalyst], randInt(120, 175)/100, true, 13.5, randInt(250, 1.5e3), 120e9);
StockMarket[catalyst] = catalystStk;
var microdyne = "Microdyne Technologies";
var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], randInt(70, 80)/100, true, 8, randInt(15e3, 30e3));
var microdyneStk = new Stock(microdyne, StockSymbols[microdyne], randInt(70, 80)/100, true, 8, randInt(15e3, 30e3), 360e9);
StockMarket[microdyne] = microdyneStk;
var titanlabs = "Titan Laboratories";
var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], randInt(50, 70)/100, true, 11, randInt(12e3, 24e3));
var titanlabsStk = new Stock(titanlabs, StockSymbols[titanlabs], randInt(50, 70)/100, true, 11, randInt(12e3, 24e3), 420e9);
StockMarket[titanlabs] = titanlabsStk;
var orders = {};
@ -411,6 +413,7 @@ function buyStock(stock, shares) {
return false;
}
// Does player have enough money?
var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
dialogBoxCreate("You do not have enough money to purchase this. You need " +
@ -418,6 +421,13 @@ function buyStock(stock, shares) {
return false;
}
// Would this purchase exceed the maximum number of shares?
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ` +
`${numeralWrapper.formatBigNumber(stock.maxShares)} shares.`);
return false;
}
var origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice;
@ -470,6 +480,7 @@ function shortStock(stock, shares, workerScript=null) {
return false;
}
// Does the player have enough money?
var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
if (tixApi) {
@ -484,6 +495,19 @@ function shortStock(stock, shares, workerScript=null) {
return false;
}
// Would this purchase exceed the maximum number of shares?
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
if (tixApi) {
workerScript.scriptRef.log("ERROR: shortStock() failed because purchasing this many short shares would exceed " +
`${stock.symbol}'s maximum number of shares.`);
} else {
dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ` +
`${stock.maxShares} shares.`);
}
return false;
}
var origTotal = stock.playerShortShares * stock.playerAvgShortPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice;
@ -1190,6 +1214,7 @@ function createStockTicker(stock) {
switch (ordType) {
case "Market Order":
var shares = Math.floor((money - COMM) / stock.price);
shares = Math.min(shares, Math.round(stock.maxShares - stock.playerShares - stock.playerShortShares));
pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null);
break;
case "Limit Order":
@ -1206,6 +1231,7 @@ function createStockTicker(stock) {
type = OrderTypes.StopBuy;
}
var shares = Math.floor((money-COMM) / price);
shares = Math.min(shares, Math.round(stock.maxShares - stock.playerShares - stock.playerShortShares));
placeOrder(stock, shares, price, type, pos);
yesNoTxtInpBoxClose();
});
@ -1384,25 +1410,26 @@ function updateStockPlayerPosition(stock) {
if (isNaN(shortPercentageGains)) { shortPercentageGains = 0; }
stock.posTxtEl.innerHTML =
"<h1 class='tooltip stock-market-position-text'>Long Position: " +
`Max Shares: ${numeralWrapper.format(stock.maxShares, "0.000a")}<br>` +
"<h3 class='tooltip stock-market-position-text'>Long Position: " +
"<span class='tooltiptext'>Shares in the long position will increase " +
"in value if the price of the corresponding stock increases</span></h1>" +
"in value if the price of the corresponding stock increases</span></h3>" +
"<br>Shares: " + numeralWrapper.format(stock.playerShares, '0,0') +
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgPx, '$0.000a') +
" (Total Cost: " + numeralWrapper.format(totalCost, '$0.000a') + ")" +
"<br>Profit: " + numeralWrapper.format(gains, '$0.000a') +
" (" + numeralWrapper.format(percentageGains, '0.00%') + ")<br><br>";
" (" + numeralWrapper.format(percentageGains, '0.00%') + ")<br>";
if (Player.bitNodeN === 8 || (hasWallStreetSF && wallStreetSFLvl >= 2)) {
stock.posTxtEl.innerHTML +=
"<h1 class='tooltip stock-market-position-text'>Short Position: " +
"<br><h3 class='tooltip stock-market-position-text'>Short Position: " +
"<span class='tooltiptext'>Shares in short position will increase " +
"in value if the price of the corresponding stock decreases</span></h1>" +
"in value if the price of the corresponding stock decreases</span></h3>" +
"<br>Shares: " + numeralWrapper.format(stock.playerShortShares, '0,0') +
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgShortPx, '$0.000a') +
" (Total Cost: " + numeralWrapper.format(shortTotalCost, '$0.000a') + ")" +
"<br>Profit: " + numeralWrapper.format(shortGains, '$0.000a') +
"<br>Average Price: " + numeralWrapper.formatMoney(stock.playerAvgShortPx) +
" (Total Cost: " + numeralWrapper.formatMoney(shortTotalCost) + ")" +
"<br>Profit: " + numeralWrapper.formatMoney(shortGains) +
" (" + numeralWrapper.format(shortPercentageGains, '0.00%') + ")" +
"<br><br><h1 class='stock-market-position-text'>Orders: </h1>";
"<br><br><h3 class='stock-market-position-text'>Orders:</h3>";
}
}

@ -73,7 +73,7 @@ import {StockMarket, StockSymbols,
SymbolToStockMap, initStockSymbols,
initSymbolToStockMap, stockMarketCycle,
processStockPrices,
displayStockMarketContent} from "./StockMarket";
displayStockMarketContent} from "./StockMarket/StockMarket";
import {Terminal, postNetburnerText} from "./Terminal";
import {KEY} from "../utils/helpers/keyCodes";
import {Page, routing} from "./ui/navigationTracking";
@ -88,6 +88,7 @@ import "../css/mainmenu.scss";
import "../css/characteroverview.scss";
import "../css/terminal.scss";
import "../css/menupages.scss";
import "../css/stockmarket.scss";
import "../css/workinprogress.scss";
import "../css/popupboxes.scss";
import "../css/gameoptions.scss";

@ -43,6 +43,10 @@ class NumeralFormatter {
formatMoney(n: number): string {
return this.format(n, "$0.000a");
}
formatBigNumber(n: number): string {
return this.format(n, "0.000a");
}
}
export const numeralWrapper = new NumeralFormatter();