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

111088
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 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 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 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. TIX API can be purchased by visiting the World Stock Exchange in-game.
@ -62,6 +63,19 @@ getStockPosition
sharesShort = pos[2]; sharesShort = pos[2];
avgPxShort = pos[3]; 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 buyStock
-------- --------

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <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="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="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -474,7 +474,8 @@
<!-- Tutorial content --> <!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container"> <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-networking-link" class="a-link-button"> Servers & Networking </a>
<a id="tutorial-hacking-link" class="a-link-button"> Hacking </a> <a id="tutorial-hacking-link" class="a-link-button"> Hacking </a>
<a id="tutorial-scripts-link" class="a-link-button"> Scripts </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-jobs-link" class="a-link-button"> Companies and Infiltration </a>
<a id="tutorial-factions-link" class="a-link-button"> Factions </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-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> <a id="tutorial-back-button" class="a-link-button"> Back </a>
<p id="tutorial-text"> </p> <p id="tutorial-text"> </p>

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

@ -40,12 +40,12 @@ import {Server, getServer, AddToAllServers,
GetServerByHostname, numCycleForGrowth} from "./Server"; GetServerByHostname, numCycleForGrowth} from "./Server";
import {Settings} from "./Settings"; import {Settings} from "./Settings";
import {SpecialServerIps} from "./SpecialServerIps"; import {SpecialServerIps} from "./SpecialServerIps";
import {Stock} from "./Stock"; import {Stock} from "./StockMarket/Stock";
import {StockMarket, StockSymbols, SymbolToStockMap, import {StockMarket, StockSymbols, SymbolToStockMap,
initStockMarket, initSymbolToStockMap, buyStock, initStockMarket, initSymbolToStockMap, buyStock,
sellStock, updateStockPlayerPosition, sellStock, updateStockPlayerPosition,
shortStock, sellShort, OrderTypes, shortStock, sellShort, OrderTypes,
PositionTypes, placeOrder, cancelOrder} from "./StockMarket"; PositionTypes, placeOrder, cancelOrder} from "./StockMarket/StockMarket";
import {post} from "./ui/postToTerminal"; import {post} from "./ui/postToTerminal";
import {TextFile, getTextFile, createTextFile} from "./TextFile"; import {TextFile, getTextFile, createTextFile} from "./TextFile";
@ -1537,6 +1537,22 @@ function NetscriptFunctions(workerScript) {
} }
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx]; 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) { buyStock : function(symbol, shares) {
if (workerScript.checkingRam) { if (workerScript.checkingRam) {
return updateStaticRam("buyStock", CONSTANTS.ScriptBuySellStockRamCost); return updateStaticRam("buyStock", CONSTANTS.ScriptBuySellStockRamCost);
@ -1556,6 +1572,7 @@ function NetscriptFunctions(workerScript) {
shares = Math.round(shares); shares = Math.round(shares);
if (shares === 0) {return 0;} if (shares === 0) {return 0;}
// Does player have enough money?
var totalPrice = stock.price * shares; var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) { if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
workerScript.scriptRef.log("Not enough money to purchase " + formatNumber(shares, 0) + " shares of " + workerScript.scriptRef.log("Not enough money to purchase " + formatNumber(shares, 0) + " shares of " +
@ -1564,6 +1581,13 @@ function NetscriptFunctions(workerScript) {
return 0; 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; var origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission); Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice; var newTotal = origTotal + totalPrice;

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

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

@ -1,5 +1,5 @@
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { getRandomInt } from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../../utils/helpers/getRandomInt";
/** /**
* Represents the valuation of a company in the World Stock Exchange. * Represents the valuation of a company in the World Stock Exchange.
@ -22,6 +22,11 @@ export class Stock {
*/ */
readonly cap: number; readonly cap: number;
/**
* Maximum number of shares that player can own (both long and short combined)
*/
readonly maxShares: number;
/** /**
* Maximum volatility * Maximum volatility
*/ */
@ -78,7 +83,8 @@ export class Stock {
mv: number = 1, mv: number = 1,
b: boolean = true, b: boolean = true,
otlkMag: number = 0, otlkMag: number = 0,
initPrice: number = 10e3) { initPrice: number = 10e3,
marketCap: number = 1e12) {
this.name = name; this.name = name;
this.symbol = symbol; this.symbol = symbol;
this.price = initPrice; this.price = initPrice;
@ -91,6 +97,10 @@ export class Stock {
this.otlkMag = otlkMag; this.otlkMag = otlkMag;
this.cap = getRandomInt(initPrice * 1e3, initPrice * 25e3); 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; 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 {Stock} from "./Stock";
import {dialogBoxCreate} from "../utils/DialogBox"; import {CONSTANTS} from "../Constants";
import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; 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, import {Reviver, Generic_toJSON,
Generic_fromJSON} from "../utils/JSONReviver"; Generic_fromJSON} from "../../utils/JSONReviver";
import {Page, routing} from "./ui/navigationTracking"; import {exceptionAlert} from "../../utils/helpers/exceptionAlert";
import {numeralWrapper} from "./ui/numeralFormat"; import {getRandomInt} from "../../utils/helpers/getRandomInt";
import {exceptionAlert} from "../utils/helpers/exceptionAlert"; import {KEY} from "../../utils/helpers/keyCodes";
import {getRandomInt} from "../utils/helpers/getRandomInt"; import {createElement} from "../../utils/uiHelpers/createElement";
import {KEY} from "../utils/helpers/keyCodes"; import {removeChildrenFromElement} from "../../utils/uiHelpers/removeChildrenFromElement";
import {createElement} from "../utils/uiHelpers/createElement"; import {removeElementById} from "../../utils/uiHelpers/removeElementById";
import {removeChildrenFromElement} from "../utils/uiHelpers/removeChildrenFromElement";
import {removeElementById} from "../utils/uiHelpers/removeElementById";
import {yesNoBoxCreate, yesNoTxtInpBoxCreate, import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxGetYesButton, yesNoBoxGetNoButton,
yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton, yesNoTxtInpBoxGetYesButton, yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput, yesNoBoxClose, yesNoTxtInpBoxGetInput, yesNoBoxClose,
yesNoTxtInpBoxClose, yesNoBoxOpen} from "../utils/YesNoBox"; yesNoTxtInpBoxClose, yesNoBoxOpen} from "../../utils/YesNoBox";
var OrderTypes = { var OrderTypes = {
LimitBuy: "Limit Buy Order", LimitBuy: "Limit Buy Order",
@ -228,135 +230,135 @@ function initStockMarket() {
const randInt = getRandomInt; const randInt = getRandomInt;
var ecorp = Locations.AevumECorp; 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; StockMarket[ecorp] = ecorpStk;
var megacorp = Locations.Sector12MegaCorp; 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; StockMarket[megacorp] = megacorpStk;
var blade = Locations.Sector12BladeIndustries; 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; StockMarket[blade] = bladeStk;
var clarke = Locations.AevumClarkeIncorporated; 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; StockMarket[clarke] = clarkeStk;
var omnitek = Locations.VolhavenOmniTekIncorporated; 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; StockMarket[omnitek] = omnitekStk;
var foursigma = Locations.Sector12FourSigma; 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; StockMarket[foursigma] = foursigmaStk;
var kuaigong = Locations.ChongqingKuaiGongInternational; 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; StockMarket[kuaigong] = kuaigongStk;
var fulcrum = Locations.AevumFulcrumTechnologies; 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; StockMarket[fulcrum] = fulcrumStk;
var storm = Locations.IshimaStormTechnologies; 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; StockMarket[storm] = stormStk;
var defcomm = Locations.NewTokyoDefComm; 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; StockMarket[defcomm] = defcommStk;
var helios = Locations.VolhavenHeliosLabs; 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; StockMarket[helios] = heliosStk;
var vitalife = Locations.NewTokyoVitaLife; 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; StockMarket[vitalife] = vitalifeStk;
var icarus = Locations.Sector12IcarusMicrosystems; 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; StockMarket[icarus] = icarusStk;
var universalenergy = Locations.Sector12UniversalEnergy; 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; StockMarket[universalenergy] = universalenergyStk;
var aerocorp = Locations.AevumAeroCorp; 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; StockMarket[aerocorp] = aerocorpStk;
var omnia = Locations.VolhavenOmniaCybersystems; 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; StockMarket[omnia] = omniaStk;
var solaris = Locations.ChongqingSolarisSpaceSystems; 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; StockMarket[solaris] = solarisStk;
var globalpharm = Locations.NewTokyoGlobalPharmaceuticals; 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; StockMarket[globalpharm] = globalpharmStk;
var nova = Locations.IshimaNovaMedical; 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; StockMarket[nova] = novaStk;
var watchdog = Locations.AevumWatchdogSecurity; 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; StockMarket[watchdog] = watchdogStk;
var lexocorp = Locations.VolhavenLexoCorp; 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; StockMarket[lexocorp] = lexocorpStk;
var rho = Locations.AevumRhoConstruction; 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; StockMarket[rho] = rhoStk;
var alpha = Locations.Sector12AlphaEnterprises; 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; StockMarket[alpha] = alphaStk;
var syscore = Locations.VolhavenSysCoreSecurities; 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; StockMarket[syscore] = syscoreStk;
var computek = Locations.VolhavenCompuTek; 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; StockMarket[computek] = computekStk;
var netlink = Locations.AevumNetLinkTechnologies; 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; StockMarket[netlink] = netlinkStk;
var omega = Locations.IshimaOmegaSoftware; 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; StockMarket[omega] = omegaStk;
var fns = Locations.Sector12FoodNStuff; 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; StockMarket[fns] = fnsStk;
var sigmacosm = "Sigma Cosmetics"; 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; StockMarket[sigmacosm] = sigmacosmStk;
var joesguns = "Joes Guns"; 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; StockMarket[joesguns] = joesgunsStk;
var catalyst = "Catalyst Ventures"; 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; StockMarket[catalyst] = catalystStk;
var microdyne = "Microdyne Technologies"; 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; StockMarket[microdyne] = microdyneStk;
var titanlabs = "Titan Laboratories"; 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; StockMarket[titanlabs] = titanlabsStk;
var orders = {}; var orders = {};
@ -411,6 +413,7 @@ function buyStock(stock, shares) {
return false; return false;
} }
// Does player have enough money?
var totalPrice = stock.price * shares; var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) { if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
dialogBoxCreate("You do not have enough money to purchase this. You need " + dialogBoxCreate("You do not have enough money to purchase this. You need " +
@ -418,6 +421,13 @@ function buyStock(stock, shares) {
return false; 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; var origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission); Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice; var newTotal = origTotal + totalPrice;
@ -470,6 +480,7 @@ function shortStock(stock, shares, workerScript=null) {
return false; return false;
} }
// Does the player have enough money?
var totalPrice = stock.price * shares; var totalPrice = stock.price * shares;
if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) { if (Player.money.lt(totalPrice + CONSTANTS.StockMarketCommission)) {
if (tixApi) { if (tixApi) {
@ -484,6 +495,19 @@ function shortStock(stock, shares, workerScript=null) {
return false; 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; var origTotal = stock.playerShortShares * stock.playerAvgShortPx;
Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission); Player.loseMoney(totalPrice + CONSTANTS.StockMarketCommission);
var newTotal = origTotal + totalPrice; var newTotal = origTotal + totalPrice;
@ -1190,6 +1214,7 @@ function createStockTicker(stock) {
switch (ordType) { switch (ordType) {
case "Market Order": case "Market Order":
var shares = Math.floor((money - COMM) / stock.price); 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); pos === PositionTypes.Long ? buyStock(stock, shares) : shortStock(stock, shares, null);
break; break;
case "Limit Order": case "Limit Order":
@ -1206,6 +1231,7 @@ function createStockTicker(stock) {
type = OrderTypes.StopBuy; type = OrderTypes.StopBuy;
} }
var shares = Math.floor((money-COMM) / price); 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); placeOrder(stock, shares, price, type, pos);
yesNoTxtInpBoxClose(); yesNoTxtInpBoxClose();
}); });
@ -1384,25 +1410,26 @@ function updateStockPlayerPosition(stock) {
if (isNaN(shortPercentageGains)) { shortPercentageGains = 0; } if (isNaN(shortPercentageGains)) { shortPercentageGains = 0; }
stock.posTxtEl.innerHTML = 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 " + "<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>Shares: " + numeralWrapper.format(stock.playerShares, '0,0') +
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgPx, '$0.000a') + "<br>Average Price: " + numeralWrapper.format(stock.playerAvgPx, '$0.000a') +
" (Total Cost: " + numeralWrapper.format(totalCost, '$0.000a') + ")" + " (Total Cost: " + numeralWrapper.format(totalCost, '$0.000a') + ")" +
"<br>Profit: " + numeralWrapper.format(gains, '$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)) { if (Player.bitNodeN === 8 || (hasWallStreetSF && wallStreetSFLvl >= 2)) {
stock.posTxtEl.innerHTML += 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 " + "<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>Shares: " + numeralWrapper.format(stock.playerShortShares, '0,0') +
"<br>Average Price: " + numeralWrapper.format(stock.playerAvgShortPx, '$0.000a') + "<br>Average Price: " + numeralWrapper.formatMoney(stock.playerAvgShortPx) +
" (Total Cost: " + numeralWrapper.format(shortTotalCost, '$0.000a') + ")" + " (Total Cost: " + numeralWrapper.formatMoney(shortTotalCost) + ")" +
"<br>Profit: " + numeralWrapper.format(shortGains, '$0.000a') + "<br>Profit: " + numeralWrapper.formatMoney(shortGains) +
" (" + numeralWrapper.format(shortPercentageGains, '0.00%') + ")" + " (" + 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, SymbolToStockMap, initStockSymbols,
initSymbolToStockMap, stockMarketCycle, initSymbolToStockMap, stockMarketCycle,
processStockPrices, processStockPrices,
displayStockMarketContent} from "./StockMarket"; displayStockMarketContent} from "./StockMarket/StockMarket";
import {Terminal, postNetburnerText} from "./Terminal"; import {Terminal, postNetburnerText} from "./Terminal";
import {KEY} from "../utils/helpers/keyCodes"; import {KEY} from "../utils/helpers/keyCodes";
import {Page, routing} from "./ui/navigationTracking"; import {Page, routing} from "./ui/navigationTracking";
@ -88,6 +88,7 @@ import "../css/mainmenu.scss";
import "../css/characteroverview.scss"; import "../css/characteroverview.scss";
import "../css/terminal.scss"; import "../css/terminal.scss";
import "../css/menupages.scss"; import "../css/menupages.scss";
import "../css/stockmarket.scss";
import "../css/workinprogress.scss"; import "../css/workinprogress.scss";
import "../css/popupboxes.scss"; import "../css/popupboxes.scss";
import "../css/gameoptions.scss"; import "../css/gameoptions.scss";

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