mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-18 21:53:50 +01:00
Merge pull request #438 from danielyxie/stock-market-update
Stock market update
This commit is contained in:
commit
c8158e1d19
@ -552,6 +552,17 @@
|
|||||||
#stock-market-container {
|
#stock-market-container {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding: 6px;
|
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-container p {
|
#stock-market-container p {
|
||||||
@ -564,6 +575,11 @@
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#stock-market-watchlist-filter {
|
||||||
|
width:50%;
|
||||||
|
margin-left:10px;
|
||||||
|
}
|
||||||
|
|
||||||
.stock-market-input {
|
.stock-market-input {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
@ -310,11 +310,23 @@ a:visited {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-tip:hover {
|
.help-tip-big {
|
||||||
|
content: '?';
|
||||||
|
padding: 3px;
|
||||||
|
margin-left: 3px;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-tip:hover,
|
||||||
|
.help-tip-big:hover {
|
||||||
background-color: #888;
|
background-color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-tip:active {
|
.help-tip:active,
|
||||||
|
.help-tip-big:active {
|
||||||
@include boxShadow(inset 0 1px 4px rgba(0, 0, 0, 0.6));
|
@include boxShadow(inset 0 1px 4px rgba(0, 0, 0, 0.6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,9 @@ getActionEstimatedSuccessChance
|
|||||||
:param string type: Type of action. See :ref:`bladeburner_action_types`
|
:param string type: Type of action. See :ref:`bladeburner_action_types`
|
||||||
:param string name: Name of action. Must be an exact match
|
:param string name: Name of action. Must be an exact match
|
||||||
|
|
||||||
Returns the estimated success chance for the specified action
|
Returns the estimated success chance for the specified action. This chance
|
||||||
|
is returned as a decimal value, NOT a percentage (e.g. if you have an estimated
|
||||||
|
success chance of 80%, then this function will return 0.80, NOT 80).
|
||||||
|
|
||||||
getActionCountRemaining
|
getActionCountRemaining
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -172,3 +172,38 @@ cancelOrder
|
|||||||
Cancels an oustanding Limit or Stop order on the stock market.
|
Cancels an oustanding Limit or Stop order on the stock market.
|
||||||
|
|
||||||
The ability to use limit and stop orders is **not** immediately available to the player and must be unlocked later on in the game.
|
The ability to use limit and stop orders is **not** immediately available to the player and must be unlocked later on in the game.
|
||||||
|
|
||||||
|
getStockVolatility
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. js:function:: getStockVolatility(sym)
|
||||||
|
|
||||||
|
:param string sym: Symbol of stock
|
||||||
|
|
||||||
|
Returns the volatility of the specified stock.
|
||||||
|
|
||||||
|
Volatility represents the maximum percentage by which a stock's price can
|
||||||
|
change every tick. The volatility is returned as a decimal value, NOT
|
||||||
|
a percentage (e.g. if a stock has a volatility of 3%, then this function will
|
||||||
|
return 0.03, NOT 3).
|
||||||
|
|
||||||
|
In order to use this function, you must first purchase access to the Four Sigma (4S)
|
||||||
|
Market Data TIX API.
|
||||||
|
|
||||||
|
getStockForecast
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. js:function:: getStockForecast(sym)
|
||||||
|
|
||||||
|
:param string sym: Symbol of stock
|
||||||
|
|
||||||
|
Returns the probability that the specified stock's price will increase
|
||||||
|
(as opposed to decrease) during the next tick.
|
||||||
|
|
||||||
|
The probability is returned as a decimal value, NOT a percentage (e.g. if a
|
||||||
|
stock has a 60% chance of increasing, then this function will return 0.6,
|
||||||
|
NOT 60).
|
||||||
|
|
||||||
|
In other words, if this function returned 0.30 for a stock, then this means
|
||||||
|
that the stock's price has a 30% chance of increasing and a 70% chance of
|
||||||
|
decreasing during the next tick.
|
||||||
|
34
index.html
34
index.html
@ -679,22 +679,44 @@
|
|||||||
after you 'reset' by installing Augmentations.
|
after you 'reset' by installing Augmentations.
|
||||||
</p>
|
</p>
|
||||||
<a id="stock-market-buy-account" class="a-link-button-inactive"> Buy WSE Account </a>
|
<a id="stock-market-buy-account" class="a-link-button-inactive"> Buy WSE Account </a>
|
||||||
|
<a id="stock-market-investopedia" class="a-link-button">Investopedia</a>
|
||||||
|
|
||||||
|
<h2> Trade Information eXchange (TIX) API </h2>
|
||||||
<p>
|
<p>
|
||||||
You can also purchase access to the World Stock Exchange's TIX API! TIX, short for
|
TIX, short for Trade Information eXchange, is the communications protocol supported by the WSE.
|
||||||
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
|
||||||
<br><br>
|
trading strategies.
|
||||||
Gaining access to the TIX API lets you write code to build automated trading
|
|
||||||
systems. In other words, you can create your own algorithmic trading strategies!
|
|
||||||
<br><br>
|
<br><br>
|
||||||
If you purchase access to the TIX API, you will retain that access even after
|
If you purchase access to the TIX API, you will retain that access even after
|
||||||
you 'reset' by installing Augmentations.
|
you 'reset' by installing Augmentations.
|
||||||
</p>
|
</p>
|
||||||
<a id="stock-market-buy-tix-api" class="a-link-button-inactive">Buy Trade Information eXchange (TIX) API Access</a>
|
<a id="stock-market-buy-tix-api" class="a-link-button-inactive">Buy Trade Information eXchange (TIX) API Access</a>
|
||||||
<a id="stock-market-investopedia" class="a-link-button">Investopedia</a>
|
|
||||||
|
<h2> Four Sigma (4S) Market Data Feed </h2>
|
||||||
|
<p>
|
||||||
|
Four Sigma's (4S) Market Data Feed provides information about stocks
|
||||||
|
that will help your trading strategies.
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<a id="stock-market-buy-4s-data" class="a-link-button-inactive tooltip">
|
||||||
|
Buy 4S Market Data Feed
|
||||||
|
</a>
|
||||||
|
<div class="help-tip-big" id="stock-market-4s-data-help-tip">?</div>
|
||||||
|
|
||||||
|
<a id="stock-market-buy-4s-tix-api" class="a-link-button-inactive tooltip">
|
||||||
|
Buy 4S Market Data TIX API Access
|
||||||
|
</a>
|
||||||
|
|
||||||
<p id="stock-market-commission"> </p>
|
<p id="stock-market-commission"> </p>
|
||||||
<a id="stock-market-mode" class="a-link-button tooltip"></a>
|
<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-expand-tickers" class="a-link-button tooltip">Expand tickers</a>
|
||||||
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
|
<a id="stock-market-collapse-tickers" class="a-link-button tooltip">Collapse tickers</a>
|
||||||
|
<br><br>
|
||||||
|
<input id="stock-market-watchlist-filter" type="text" placeholder="Filter Stocks by symbol (comma-separated list)"> </input>
|
||||||
|
<a id="stock-market-watchlist-filter-update" class="a-link-button"> Update Watchlist </a>
|
||||||
<ul id="stock-market-list" style="list-style:none;">
|
<ul id="stock-market-list" style="list-style:none;">
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,5 +101,5 @@
|
|||||||
"watch": "webpack --watch --mode production",
|
"watch": "webpack --watch --mode production",
|
||||||
"watch:dev": "webpack --watch --mode development"
|
"watch:dev": "webpack --watch --mode development"
|
||||||
},
|
},
|
||||||
"version": "0.35.1"
|
"version": "0.40.2"
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,8 @@ let CONSTANTS = {
|
|||||||
//Stock market constants
|
//Stock market constants
|
||||||
WSEAccountCost: 200e6,
|
WSEAccountCost: 200e6,
|
||||||
TIXAPICost: 5e9,
|
TIXAPICost: 5e9,
|
||||||
|
MarketData4SCost: 1e9,
|
||||||
|
MarketDataTixApi4SCost: 20e9,
|
||||||
StockMarketCommission: 100e3,
|
StockMarketCommission: 100e3,
|
||||||
|
|
||||||
//Hospital/Health
|
//Hospital/Health
|
||||||
@ -492,9 +494,9 @@ let CONSTANTS = {
|
|||||||
|
|
||||||
LatestUpdate:
|
LatestUpdate:
|
||||||
"v0.40.2<br>" +
|
"v0.40.2<br>" +
|
||||||
|
"------------------------------<br>" +
|
||||||
"* Bladeburner Changes:<br>" +
|
"* Bladeburner Changes:<br>" +
|
||||||
"*** Added getSkillUpgradeCost() Netscript function to the API<br>" +
|
"*** Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API<br>" +
|
||||||
"*** Added getBonusTime() Netscript function to the API<br>" +
|
|
||||||
"*** Buffed the effects of many Bladeburner Augmentations<br>" +
|
"*** Buffed the effects of many Bladeburner Augmentations<br>" +
|
||||||
"*** The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money<br>" +
|
"*** The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money<br>" +
|
||||||
"*** Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level<br>" +
|
"*** Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level<br>" +
|
||||||
@ -504,6 +506,12 @@ let CONSTANTS = {
|
|||||||
"*** The number (count) of Operations should now increase significantly faster<br>" +
|
"*** The number (count) of Operations should now increase significantly faster<br>" +
|
||||||
"*** There are now, on average, more Synthoid communities in a city<br>" +
|
"*** There are now, on average, more Synthoid communities in a city<br>" +
|
||||||
"*** If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation<br>" +
|
"*** If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation<br>" +
|
||||||
|
"------------------------------<br>" +
|
||||||
|
"* Stock Market Changes:<br>" +
|
||||||
|
"***Added a watchlist filter feature to the UI that allows you to specify which stocks to show<br>" +
|
||||||
|
"***Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks<br>" +
|
||||||
|
"***Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript<br>" +
|
||||||
|
"------------------------------<br>" +
|
||||||
"* There is now a setting for enabling/disabling the popup that appears when you are hospitalized<br>" +
|
"* There is now a setting for enabling/disabling the popup that appears when you are hospitalized<br>" +
|
||||||
"* Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-)<br>" +
|
"* Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-)<br>" +
|
||||||
"* Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-)<br>" +
|
"* Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-)<br>" +
|
||||||
|
@ -1599,6 +1599,36 @@ function NetscriptFunctions(workerScript) {
|
|||||||
};
|
};
|
||||||
return cancelOrder(params, workerScript);
|
return cancelOrder(params, workerScript);
|
||||||
},
|
},
|
||||||
|
getStockVolatility : function(symbol) {
|
||||||
|
if (workerScript.checkingRam) {
|
||||||
|
return updateStaticRam("getStockVolatility", CONSTANTS.ScriptBuySellStockRamCost);
|
||||||
|
}
|
||||||
|
updateDynamicRam("getStockVolatility", CONSTANTS.ScriptBuySellStockRamCost);
|
||||||
|
if (!Player.has4SDataTixApi) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockVolatility()");
|
||||||
|
}
|
||||||
|
var stock = SymbolToStockMap[symbol];
|
||||||
|
if (stock == null) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into getStockVolatility()");
|
||||||
|
}
|
||||||
|
return stock.mv / 100; //Convert from percentage to decimal
|
||||||
|
},
|
||||||
|
getStockForecast : function(symbol) {
|
||||||
|
if (workerScript.checkingRam) {
|
||||||
|
return updateStaticRam("getStockForecast", CONSTANTS.ScriptBuySellStockRamCost);
|
||||||
|
}
|
||||||
|
updateDynamicRam("getStockForecast", CONSTANTS.ScriptBuySellStockRamCost);
|
||||||
|
if (!Player.has4SDataTixApi) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "You don't have 4S Market Data TIX API Access! Cannot use getStockForecast()");
|
||||||
|
}
|
||||||
|
var stock = SymbolToStockMap[symbol];
|
||||||
|
if (stock == null) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "ERROR: Invalid stock symbol passed into getStockForecast()");
|
||||||
|
}
|
||||||
|
var forecast = 50;
|
||||||
|
stock.b ? forecast += stock.otlkMag : forecast -= stock.otlkMag;
|
||||||
|
return forecast / 100; //Convert from percentage to decimal
|
||||||
|
},
|
||||||
getPurchasedServerLimit : function() {
|
getPurchasedServerLimit : function() {
|
||||||
if (workerScript.checkingRam) {
|
if (workerScript.checkingRam) {
|
||||||
return updateStaticRam("getPurchasedServerLimit", CONSTANTS.ScriptGetPurchasedServerLimit);
|
return updateStaticRam("getPurchasedServerLimit", CONSTANTS.ScriptGetPurchasedServerLimit);
|
||||||
@ -3744,6 +3774,21 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeRejectMsg(workerScript, "getCityChaos() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
throw makeRuntimeRejectMsg(workerScript, "getCityChaos() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||||
"at the Bladeburner division or because you do not have Source-File 7");
|
"at the Bladeburner division or because you do not have Source-File 7");
|
||||||
},
|
},
|
||||||
|
getCity : function() {
|
||||||
|
if (workerScript.checkingRam) {
|
||||||
|
return updateStaticRam("getCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||||
|
}
|
||||||
|
updateDynamicRam("getCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||||
|
if (Player.bladeburner instanceof Bladeburner && (Player.bitNodeN === 7 || hasBladeburner2079SF)) {
|
||||||
|
try {
|
||||||
|
return Player.bladeburner.city;
|
||||||
|
} catch(e) {
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "Bladeburner.getCity() failed with exception: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw makeRuntimeRejectMsg(workerScript, "getCity() failed because you do not currently have access to the Bladeburner API. This is either because you are not currently employed " +
|
||||||
|
"at the Bladeburner division or because you do not have Source-File 7");
|
||||||
|
},
|
||||||
switchCity : function(cityName) {
|
switchCity : function(cityName) {
|
||||||
if (workerScript.checkingRam) {
|
if (workerScript.checkingRam) {
|
||||||
return updateStaticRam("switchCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
return updateStaticRam("switchCity", CONSTANTS.ScriptBladeburnerApiBaseRamCost);
|
||||||
|
@ -173,6 +173,8 @@ function PlayerObject() {
|
|||||||
//Stock Market
|
//Stock Market
|
||||||
this.hasWseAccount = false;
|
this.hasWseAccount = false;
|
||||||
this.hasTixApiAccess = false;
|
this.hasTixApiAccess = false;
|
||||||
|
this.has4SData = false;
|
||||||
|
this.has4SDataTixApi = false;
|
||||||
|
|
||||||
//Gang
|
//Gang
|
||||||
this.gang = 0;
|
this.gang = 0;
|
||||||
|
@ -10,7 +10,11 @@ import {Reviver, Generic_toJSON,
|
|||||||
Generic_fromJSON} from "../utils/JSONReviver";
|
Generic_fromJSON} from "../utils/JSONReviver";
|
||||||
import {Page, routing} from "./ui/navigationTracking";
|
import {Page, routing} from "./ui/navigationTracking";
|
||||||
import numeral from "numeral/min/numeral.min";
|
import numeral from "numeral/min/numeral.min";
|
||||||
|
import {exceptionAlert} from "../utils/helpers/exceptionAlert";
|
||||||
import {getRandomInt} from "../utils/helpers/getRandomInt";
|
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 {removeElementById} from "../utils/uiHelpers/removeElementById";
|
||||||
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
import {yesNoBoxCreate, yesNoTxtInpBoxCreate,
|
||||||
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
|
yesNoBoxGetYesButton, yesNoBoxGetNoButton,
|
||||||
@ -409,6 +413,7 @@ function stockMarketCycle() {
|
|||||||
for (var name in StockMarket) {
|
for (var name in StockMarket) {
|
||||||
if (StockMarket.hasOwnProperty(name)) {
|
if (StockMarket.hasOwnProperty(name)) {
|
||||||
var stock = StockMarket[name];
|
var stock = StockMarket[name];
|
||||||
|
if (!(stock instanceof Stock)) {continue;}
|
||||||
var thresh = 0.6;
|
var thresh = 0.6;
|
||||||
if (stock.b) {thresh = 0.4;}
|
if (stock.b) {thresh = 0.4;}
|
||||||
if (Math.random() < thresh) {
|
if (Math.random() < thresh) {
|
||||||
@ -695,18 +700,29 @@ var COMM = CONSTANTS.StockMarketCommission;
|
|||||||
function displayStockMarketContent() {
|
function displayStockMarketContent() {
|
||||||
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
|
if (Player.hasWseAccount == null) {Player.hasWseAccount = false;}
|
||||||
if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;}
|
if (Player.hasTixApiAccess == null) {Player.hasTixApiAccess = false;}
|
||||||
|
if (Player.has4SData == null) {Player.has4SData = false;}
|
||||||
|
if (Player.has4SDataTixApi == null) {Player.has4SDataTixApi = false;}
|
||||||
|
|
||||||
|
function stylePurchaseButton(btn, cost, flag, initMsg, purchasedMsg) {
|
||||||
|
btn.innerText = initMsg;
|
||||||
|
btn.classList.remove("a-link-button");
|
||||||
|
btn.classList.remove("a-link-button-bought");
|
||||||
|
btn.classList.remove("a-link-button-inactive");
|
||||||
|
if (!flag && Player.money.gte(cost)) {
|
||||||
|
btn.classList.add("a-link-button");
|
||||||
|
} else if (flag) {
|
||||||
|
btn.innerText = purchasedMsg;
|
||||||
|
btn.classList.add("a-link-button-bought");
|
||||||
|
} else {
|
||||||
|
btn.classList.add("a-link-button-inactive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Purchase WSE Account button
|
//Purchase WSE Account button
|
||||||
var wseAccountButton = clearEventListeners("stock-market-buy-account");
|
var wseAccountButton = clearEventListeners("stock-market-buy-account");
|
||||||
wseAccountButton.innerText = "Buy WSE Account - " + numeral(CONSTANTS.WSEAccountCost).format('($0.000a)');
|
stylePurchaseButton(wseAccountButton, CONSTANTS.WSEAccountCost, Player.hasWseAccount,
|
||||||
if (!Player.hasWseAccount && Player.money.gte(CONSTANTS.WSEAccountCost)) {
|
"Buy WSE Account - " + numeral(CONSTANTS.WSEAccountCost).format('($0.000a)'),
|
||||||
wseAccountButton.setAttribute("class", "a-link-button");
|
"WSE Account - Purchased");
|
||||||
} else if (Player.hasWseAccount){
|
|
||||||
wseAccountButton.innerText = "WSE Account - Purchased";
|
|
||||||
wseAccountButton.setAttribute("class", "a-link-button-bought");
|
|
||||||
} else {
|
|
||||||
wseAccountButton.setAttribute("class", "a-link-button-inactive");
|
|
||||||
}
|
|
||||||
wseAccountButton.addEventListener("click", function() {
|
wseAccountButton.addEventListener("click", function() {
|
||||||
Player.hasWseAccount = true;
|
Player.hasWseAccount = true;
|
||||||
initStockMarket();
|
initStockMarket();
|
||||||
@ -718,16 +734,9 @@ function displayStockMarketContent() {
|
|||||||
|
|
||||||
//Purchase TIX API Access account
|
//Purchase TIX API Access account
|
||||||
var tixApiAccessButton = clearEventListeners("stock-market-buy-tix-api");
|
var tixApiAccessButton = clearEventListeners("stock-market-buy-tix-api");
|
||||||
tixApiAccessButton.innerText = "Buy Trade Information eXchange (TIX) API Access - " +
|
stylePurchaseButton(tixApiAccessButton, CONSTANTS.TIXAPICost, Player.hasTixApiAccess,
|
||||||
numeral(CONSTANTS.TIXAPICost).format('($0.000a)');
|
"Buy Trade Information eXchange (TIX) API Access - " + numeral(CONSTANTS.TIXAPICost).format('($0.000a)'),
|
||||||
if (!Player.hasTixApiAccess && Player.money.gte(CONSTANTS.TIXAPICost)) {
|
"TIX API Access - Purchased");
|
||||||
tixApiAccessButton.setAttribute("class", "a-link-button");
|
|
||||||
} else if(Player.hasTixApiAccess) {
|
|
||||||
tixApiAccessButton.innerText = "Trade Information eXchange (TIX) API Access - Purchased"
|
|
||||||
tixApiAccessButton.setAttribute("class", "a-link-button-bought");
|
|
||||||
} else {
|
|
||||||
tixApiAccessButton.setAttribute("class", "a-link-button-inactive");
|
|
||||||
}
|
|
||||||
tixApiAccessButton.addEventListener("click", function() {
|
tixApiAccessButton.addEventListener("click", function() {
|
||||||
Player.hasTixApiAccess = true;
|
Player.hasTixApiAccess = true;
|
||||||
Player.loseMoney(CONSTANTS.TIXAPICost);
|
Player.loseMoney(CONSTANTS.TIXAPICost);
|
||||||
@ -735,9 +744,76 @@ function displayStockMarketContent() {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Purchase Four Sigma Market Data Feed
|
||||||
|
var marketDataButton = clearEventListeners("stock-market-buy-4s-data");
|
||||||
|
stylePurchaseButton(marketDataButton, CONSTANTS.MarketData4SCost, Player.has4SData,
|
||||||
|
"Buy 4S Market Data Access - " + numeral(CONSTANTS.MarketData4SCost).format('($0.000a)'),
|
||||||
|
"4S Market Data - Purchased");
|
||||||
|
marketDataButton.addEventListener("click", function() {
|
||||||
|
Player.has4SData = true;
|
||||||
|
Player.loseMoney(CONSTANTS.MarketData4SCost);
|
||||||
|
displayStockMarketContent();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
marketDataButton.appendChild(createElement("span", {
|
||||||
|
class:"tooltiptext",
|
||||||
|
innerText:"Lets you view additional pricing and volatility information about stocks"
|
||||||
|
}));
|
||||||
|
marketDataButton.style.marginRight = "2px"; //Adjusts following help tip to be slightly closer
|
||||||
|
|
||||||
|
//4S Market Data Help Tip
|
||||||
|
var marketDataHelpTip = clearEventListeners("stock-market-4s-data-help-tip");
|
||||||
|
marketDataHelpTip.style.marginTop = "10px";
|
||||||
|
marketDataHelpTip.addEventListener("click", ()=>{
|
||||||
|
dialogBoxCreate("Access to the 4S Market Data feed will display two additional pieces " +
|
||||||
|
"of information about each stock: Price Forecast & Volatility<br><br>" +
|
||||||
|
"Price Forecast indicates the probability the stock has of increasing or " +
|
||||||
|
"decreasing. A '+' forecast means the stock has a higher chance of increasing " +
|
||||||
|
"than decreasing, and a '-' means the opposite. The number of '+/-' symbols " +
|
||||||
|
"is used to illustrate the magnitude of these probabilities. For example, " +
|
||||||
|
"'+++' means that the stock has a significantly higher chance of increasing " +
|
||||||
|
"than decreasing, while '+' means that the stock only has a slightly higher chance " +
|
||||||
|
"of increasing than decreasing.<br><br>" +
|
||||||
|
"Volatility represents the maximum percentage by which a stock's price " +
|
||||||
|
"can change every tick (a tick occurs every few seconds while the game " +
|
||||||
|
"is running).<br><br>" +
|
||||||
|
"A stock's price forecast can change over time. This is also affected by volatility. " +
|
||||||
|
"The more volatile a stock is, the more its price forecast will change.");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Purchase Four Sigma Market Data TIX API (Requires TIX API Access)
|
||||||
|
var marketDataTixButton = clearEventListeners("stock-market-buy-4s-tix-api");
|
||||||
|
stylePurchaseButton(marketDataTixButton, CONSTANTS.MarketDataTixApi4SCost, Player.has4SDataTixApi,
|
||||||
|
"Buy 4S Market Data TIX API Access - " + numeral(CONSTANTS.MarketDataTixApi4SCost).format('($0.000a)'),
|
||||||
|
"4S Market Data TIX API - Purchased");
|
||||||
|
if (Player.hasTixApiAccess) {
|
||||||
|
marketDataTixButton.addEventListener("click", function() {
|
||||||
|
Player.has4SDataTixApi = true;
|
||||||
|
Player.loseMoney(CONSTANTS.MarketDataTixApi4SCost);
|
||||||
|
displayStockMarketContent();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
marketDataTixButton.appendChild(createElement("span", {
|
||||||
|
class:"tooltiptext",
|
||||||
|
innerText:"Lets you access 4S Market Data through Netscript"
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
marketDataTixButton.classList.remove("a-link-button");
|
||||||
|
marketDataTixButton.classList.remove("a-link-button-bought");
|
||||||
|
marketDataTixButton.classList.remove("a-link-button-inactive");
|
||||||
|
marketDataTixButton.classList.add("a-link-button-inactive");
|
||||||
|
marketDataTixButton.appendChild(createElement("span", {
|
||||||
|
class:"tooltiptext",
|
||||||
|
innerText:"Requires TIX API Access"
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var stockList = document.getElementById("stock-market-list");
|
var stockList = document.getElementById("stock-market-list");
|
||||||
if (stockList == null) {return;}
|
if (stockList == null) {return;}
|
||||||
|
|
||||||
|
//If Player doesn't have account, clear stocks UI and return
|
||||||
if (!Player.hasWseAccount) {
|
if (!Player.hasWseAccount) {
|
||||||
stockMarketContentCreated = false;
|
stockMarketContentCreated = false;
|
||||||
while (stockList.firstChild) {
|
while (stockList.firstChild) {
|
||||||
@ -834,14 +910,32 @@ function displayStockMarketContent() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var name in StockMarket) {
|
//Watchlish filter
|
||||||
if (StockMarket.hasOwnProperty(name)) {
|
var watchlistFilter = clearEventListeners("stock-market-watchlist-filter");
|
||||||
var stock = StockMarket[name];
|
var watchlistUpdateBtn = clearEventListeners("stock-market-watchlist-filter-update");
|
||||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
if (watchlistFilter && watchlistUpdateBtn) {
|
||||||
createStockTicker(stock);
|
//Initialize value in watchlist
|
||||||
|
if (StockMarket.watchlistFilter) {
|
||||||
|
watchlistFilter.value = StockMarket.watchlistFilter; //Remove whitespace
|
||||||
}
|
}
|
||||||
|
watchlistUpdateBtn.addEventListener("click", ()=> {
|
||||||
|
let filterValue = watchlistFilter.value.toString();
|
||||||
|
StockMarket.watchlistFilter = filterValue.replace(/\s/g, '');
|
||||||
|
if (stockMarketPortfolioMode) {
|
||||||
|
switchToPortfolioMode();
|
||||||
|
} else {
|
||||||
|
switchToDisplayAllMode();
|
||||||
}
|
}
|
||||||
setStockTickerClickHandlers(); //Clicking headers opens/closes panels
|
});
|
||||||
|
watchlistFilter.addEventListener("keyup", (e)=>{
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.keyCode === KEY.ENTER) {watchlistUpdateBtn.click();}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.warn("Stock Market Watchlist DOM elements could not be found");
|
||||||
|
}
|
||||||
|
|
||||||
|
createAllStockTickers();
|
||||||
stockMarketContentCreated = true;
|
stockMarketContentCreated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,27 +943,46 @@ function displayStockMarketContent() {
|
|||||||
for (var name in StockMarket) {
|
for (var name in StockMarket) {
|
||||||
if (StockMarket.hasOwnProperty(name)) {
|
if (StockMarket.hasOwnProperty(name)) {
|
||||||
var stock = StockMarket[name];
|
var stock = StockMarket[name];
|
||||||
|
if (stock instanceof Stock) {
|
||||||
updateStockTicker(stock, null);
|
updateStockTicker(stock, null);
|
||||||
updateStockOrderList(stock);
|
updateStockOrderList(stock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Displays only stocks you have position/order in
|
//Displays only stocks you have position/order in
|
||||||
function switchToPortfolioMode() {
|
function switchToPortfolioMode() {
|
||||||
stockMarketPortfolioMode = true;
|
stockMarketPortfolioMode = true;
|
||||||
var stockList = document.getElementById("stock-market-list");
|
|
||||||
if (stockList == null) {return;}
|
|
||||||
var modeBtn = clearEventListeners("stock-market-mode");
|
var modeBtn = clearEventListeners("stock-market-mode");
|
||||||
if (modeBtn) {
|
if (modeBtn) {
|
||||||
modeBtn.innerHTML = "Switch to 'All stocks' Mode" +
|
modeBtn.innerHTML = "Switch to 'All stocks' Mode" +
|
||||||
"<span class='tooltiptext'>Displays all stocks on the WSE</span>";
|
"<span class='tooltiptext'>Displays all stocks on the WSE</span>";
|
||||||
modeBtn.addEventListener("click", switchToDisplayAllMode);
|
modeBtn.addEventListener("click", switchToDisplayAllMode);
|
||||||
}
|
}
|
||||||
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
|
createAllStockTickers();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Displays all stocks
|
||||||
|
function switchToDisplayAllMode() {
|
||||||
|
stockMarketPortfolioMode = false;
|
||||||
|
var modeBtn = clearEventListeners("stock-market-mode");
|
||||||
|
if (modeBtn) {
|
||||||
|
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
||||||
|
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
||||||
|
modeBtn.addEventListener("click", switchToPortfolioMode);
|
||||||
|
}
|
||||||
|
createAllStockTickers();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAllStockTickers() {
|
||||||
|
var stockList = document.getElementById("stock-market-list");
|
||||||
|
if (stockList == null) {
|
||||||
|
exceptionAlert("Error creating Stock Tickers UI. DOM element with ID 'stock-market-list' could not be found");
|
||||||
|
}
|
||||||
|
removeChildrenFromElement(stockList);
|
||||||
|
|
||||||
//Get Order book (create it if it hasn't been created)
|
|
||||||
var orderBook = StockMarket["Orders"];
|
var orderBook = StockMarket["Orders"];
|
||||||
if (orderBook == null) {
|
if (orderBook == null) {
|
||||||
var orders = {};
|
var orders = {};
|
||||||
@ -881,41 +994,30 @@ function switchToPortfolioMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StockMarket["Orders"] = orders;
|
StockMarket["Orders"] = orders;
|
||||||
|
orderBook = StockMarket["Orders"];
|
||||||
|
}
|
||||||
|
|
||||||
|
let watchlist = null;
|
||||||
|
if (StockMarket.watchlistFilter != null && StockMarket.watchlistFilter !== "") {
|
||||||
|
let filter = StockMarket.watchlistFilter.replace(/\s/g, '');
|
||||||
|
watchlist = filter.split(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var name in StockMarket) {
|
for (var name in StockMarket) {
|
||||||
if (StockMarket.hasOwnProperty(name)) {
|
if (StockMarket.hasOwnProperty(name)) {
|
||||||
var stock = StockMarket[name];
|
var stock = StockMarket[name];
|
||||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
||||||
var stockOrders = orderBook[stock.symbol];
|
if (watchlist && !watchlist.includes(stock.symbol)) {continue;} //Watchlist filtering
|
||||||
|
|
||||||
|
let stockOrders = orderBook[stock.symbol];
|
||||||
|
if (stockMarketPortfolioMode) {
|
||||||
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
|
if (stock.playerShares === 0 && stock.playerShortShares === 0 &&
|
||||||
stockOrders.length === 0) {continue;}
|
stockOrders.length === 0) {continue;}
|
||||||
|
}
|
||||||
createStockTicker(stock);
|
createStockTicker(stock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setStockTickerClickHandlers();
|
setStockTickerClickHandlers(); //Clicking headers opens/closes panels
|
||||||
}
|
|
||||||
|
|
||||||
//Displays all stocks
|
|
||||||
function switchToDisplayAllMode() {
|
|
||||||
stockMarketPortfolioMode = false;
|
|
||||||
var stockList = document.getElementById("stock-market-list");
|
|
||||||
if (stockList == null) {return;}
|
|
||||||
var modeBtn = clearEventListeners("stock-market-mode");
|
|
||||||
if (modeBtn) {
|
|
||||||
modeBtn.innerHTML = "Switch to 'Portfolio' Mode" +
|
|
||||||
"<span class='tooltiptext'>Displays only the stocks for which you have shares or orders</span>";
|
|
||||||
modeBtn.addEventListener("click", switchToPortfolioMode);
|
|
||||||
}
|
|
||||||
while(stockList.firstChild) {stockList.removeChild(stockList.firstChild);}
|
|
||||||
for (var name in StockMarket) {
|
|
||||||
if (StockMarket.hasOwnProperty(name)) {
|
|
||||||
var stock = StockMarket[name];
|
|
||||||
if (!(stock instanceof Stock)) {continue;} //orders property is an array
|
|
||||||
createStockTicker(stock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setStockTickerClickHandlers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createStockTicker(stock) {
|
function createStockTicker(stock) {
|
||||||
@ -1196,10 +1298,25 @@ function updateStockTicker(stock, increase) {
|
|||||||
var hdr = document.getElementById(tickerId + "-hdr");
|
var hdr = document.getElementById(tickerId + "-hdr");
|
||||||
|
|
||||||
if (hdr == null) {
|
if (hdr == null) {
|
||||||
if (!stockMarketPortfolioMode) {console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);}
|
if (!stockMarketPortfolioMode) {
|
||||||
|
let watchlist = StockMarket.watchlistFilter;
|
||||||
|
if (watchlist !== "" && watchlist.includes(stock.symbol)) {
|
||||||
|
console.log("ERROR: Couldn't find ticker element for stock: " + stock.symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hdr.innerHTML = stock.name + " - " + stock.symbol + " - " + numeral(stock.price).format('($0.000a)');
|
let hdrText = stock.name + " (" + stock.symbol + ") - " + numeral(stock.price).format('($0.000a)');
|
||||||
|
if (Player.has4SData) {
|
||||||
|
hdrText += " - Volatility: " + numeral(stock.mv).format('0,0.00') + "%" +
|
||||||
|
" - Price Forecast: ";
|
||||||
|
if (stock.b) {
|
||||||
|
hdrText += "+".repeat(Math.floor(stock.otlkMag/10) + 1);
|
||||||
|
} else {
|
||||||
|
hdrText += "-".repeat(Math.floor(stock.otlkMag/10) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hdr.innerText = hdrText;
|
||||||
if (increase != null) {
|
if (increase != null) {
|
||||||
increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
|
increase ? hdr.style.color = "#66ff33" : hdr.style.color = "red";
|
||||||
}
|
}
|
||||||
@ -1280,7 +1397,13 @@ function updateStockOrderList(stock) {
|
|||||||
var tickerId = "stock-market-ticker-" + stock.symbol;
|
var tickerId = "stock-market-ticker-" + stock.symbol;
|
||||||
var orderList = document.getElementById(tickerId + "-order-list");
|
var orderList = document.getElementById(tickerId + "-order-list");
|
||||||
if (orderList == null) {
|
if (orderList == null) {
|
||||||
if (!stockMarketPortfolioMode) {console.log("ERROR: Could not find order list for " + stock.symbol);}
|
//Log only if its a valid error
|
||||||
|
if (!stockMarketPortfolioMode) {
|
||||||
|
let watchlist = StockMarket.watchlistFilter;
|
||||||
|
if (watchlist !== "" && watchlist.includes(stock.symbol)) {
|
||||||
|
console.log("ERROR: Could not find order list for " + stock.symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user