mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-01-20 13:01:27 +01:00
Stock transactions can now influence forecast in addition to price. Several more minor bug/UI fixes
This commit is contained in:
parent
8726946d4a
commit
585e1ac7aa
@ -73,6 +73,14 @@ be sold at $98.01, and so on.
|
|||||||
This is an important concept to keep in mind if you are trying to purchase/sell a
|
This is an important concept to keep in mind if you are trying to purchase/sell a
|
||||||
large number of shares, as **it can negatively affect your profits**.
|
large number of shares, as **it can negatively affect your profits**.
|
||||||
|
|
||||||
|
Transactions Influencing Stock Forecast
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
In addition to influencing stock price, buying or selling a large number of shares
|
||||||
|
of a stock will also influence that stock's "forecast". The forecast is the likelihood
|
||||||
|
that the stock will increase or decrease in price. The magnitude of this effect depends
|
||||||
|
on the number of shares being transacted. More shares will have a bigger effect on the
|
||||||
|
stock forecast.
|
||||||
|
|
||||||
.. _gameplay_stock_market_order_types:
|
.. _gameplay_stock_market_order_types:
|
||||||
|
|
||||||
Order Types
|
Order Types
|
||||||
|
@ -27,6 +27,7 @@ secrets that you've been searching for.
|
|||||||
Script Editors <scripteditors>
|
Script Editors <scripteditors>
|
||||||
Game Frozen or Stuck? <gamefrozen>
|
Game Frozen or Stuck? <gamefrozen>
|
||||||
Guides & Tips <guidesandtips>
|
Guides & Tips <guidesandtips>
|
||||||
|
Tools & Resources <toolsandresources>
|
||||||
Changelog <changelog>
|
Changelog <changelog>
|
||||||
Donate <https://paypal.me/danielyxie>
|
Donate <https://paypal.me/danielyxie>
|
||||||
|
|
||||||
|
23
doc/source/toolsandresources.rst
Normal file
23
doc/source/toolsandresources.rst
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Tools & Resources
|
||||||
|
=================
|
||||||
|
|
||||||
|
Official Script Repository
|
||||||
|
--------------------------
|
||||||
|
There are plans to create an official repository of Bitburner scripts. As of right now,
|
||||||
|
this is not a priority and has not been started. However, if you'd like
|
||||||
|
to contribute scripts now, you can find the repository
|
||||||
|
`here <https://github.com/bitburner-official/bitburner-scripts>`_ and submit pull requests.
|
||||||
|
|
||||||
|
Visual Studio Code Extension
|
||||||
|
----------------------------
|
||||||
|
One user created a Bitburner extension for the Visual Studio Code (VSCode) editor.
|
||||||
|
|
||||||
|
This extension includes several features such as:
|
||||||
|
|
||||||
|
* Dynamic RAM calculation
|
||||||
|
* RAM Usage breakdown
|
||||||
|
* Typescript definition files with jsdoc comments
|
||||||
|
* Netscript syntax highlighting
|
||||||
|
|
||||||
|
You can find more information and download links
|
||||||
|
`on this reddit post <https://www.reddit.com/r/Bitburner/comments/bh48y2/visual_studio_code_ram_calculator_extra/>`_.
|
@ -2105,17 +2105,6 @@ function augmentationExists(name) {
|
|||||||
return Augmentations.hasOwnProperty(name);
|
return Augmentations.hasOwnProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Used for testing balance
|
|
||||||
function giveAllAugmentations() {
|
|
||||||
for (var name in Augmentations) {
|
|
||||||
var aug = Augmentations[name];
|
|
||||||
if (aug == null) {continue;}
|
|
||||||
var ownedAug = new PlayerOwnedAugmentation(name);
|
|
||||||
Player.augmentations.push(ownedAug);
|
|
||||||
}
|
|
||||||
Player.reapplyAllAugmentations();
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayAugmentationsContent(contentEl) {
|
function displayAugmentationsContent(contentEl) {
|
||||||
removeChildrenFromElement(contentEl);
|
removeChildrenFromElement(contentEl);
|
||||||
contentEl.appendChild(createElement("h1", {
|
contentEl.appendChild(createElement("h1", {
|
||||||
|
@ -205,6 +205,7 @@ export class CodingContract {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
placeholder: "Enter Solution here",
|
placeholder: "Enter Solution here",
|
||||||
|
width: "50%",
|
||||||
}) as HTMLInputElement;
|
}) as HTMLInputElement;
|
||||||
solveBtn = createElement("a", {
|
solveBtn = createElement("a", {
|
||||||
class: "a-link-button",
|
class: "a-link-button",
|
||||||
|
@ -278,7 +278,7 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
v0.47.0
|
v0.47.0
|
||||||
* Stock Market changes:
|
* Stock Market changes:
|
||||||
** Implemented spread. Stock's now have bid and ask prices at which transactions occur
|
** Implemented spread. Stock's now have bid and ask prices at which transactions occur
|
||||||
** Large transactions will now influence a stock's price.
|
** Large transactions will now influence a stock's price and forecast
|
||||||
** This "influencing" can take effect in the middle of a transaction
|
** This "influencing" can take effect in the middle of a transaction
|
||||||
** See documentation for more details on these changes
|
** See documentation for more details on these changes
|
||||||
** Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API
|
** Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API
|
||||||
@ -286,12 +286,16 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
|
|
||||||
* Re-sleeves can no longer have the NeuroFlux Governor augmentation
|
* Re-sleeves can no longer have the NeuroFlux Governor augmentation
|
||||||
** This is just a temporary patch until the mechanic gets re-worked
|
** This is just a temporary patch until the mechanic gets re-worked
|
||||||
|
|
||||||
|
* Corporation employees no longer have an "age" stat
|
||||||
|
* Bug Fix: Corporation employees stats should no longer become negative
|
||||||
* Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios
|
* Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios
|
||||||
* Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server
|
* Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server
|
||||||
* Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang
|
* Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang
|
||||||
|
* Bug Fix: getAugmentationsFromFaction() & purchaseAugmentation() functions should now work properly if you have a gang
|
||||||
* Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game
|
* Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game
|
||||||
* Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes
|
* Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes
|
||||||
* Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads
|
* Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads
|
||||||
|
* Bug Fix: Faction UI should now automatically update reputation
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,24 @@ const infoStyleMarkup = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Info extends React.Component<IProps, any> {
|
export class Info extends React.Component<IProps, any> {
|
||||||
render() {
|
constructor(props: IProps) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
const formattedRep = numeralWrapper.format(this.props.faction.playerReputation, "0.000a");
|
this.getFavorGainText = this.getFavorGainText.bind(this);
|
||||||
|
this.getReputationText = this.getReputationText.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFavorGainText(): string {
|
||||||
const favorGain = this.props.faction.getFavorGain()[0];
|
const favorGain = this.props.faction.getFavorGain()[0];
|
||||||
|
return `You will earn ${numeralWrapper.format(favorGain, "0,0")} faction favor upon resetting after installing an Augmentation`
|
||||||
|
}
|
||||||
|
|
||||||
|
getReputationText(): string {
|
||||||
|
const formattedRep = numeralWrapper.format(this.props.faction.playerReputation, "0.000a");
|
||||||
|
return `Reputation: ${formattedRep}`
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const favorTooltip = "Faction favor increases the rate at which you earn reputation for " +
|
const favorTooltip = "Faction favor increases the rate at which you earn reputation for " +
|
||||||
"this faction by 1% per favor. Faction favor is gained whenever you " +
|
"this faction by 1% per favor. Faction favor is gained whenever you " +
|
||||||
"reset after installing an Augmentation. The amount of " +
|
"reset after installing an Augmentation. The amount of " +
|
||||||
@ -51,8 +65,8 @@ export class Info extends React.Component<IProps, any> {
|
|||||||
<p style={blockStyleMarkup}>-------------------------</p>
|
<p style={blockStyleMarkup}>-------------------------</p>
|
||||||
<AutoupdatingParagraph
|
<AutoupdatingParagraph
|
||||||
intervalTime={5e3}
|
intervalTime={5e3}
|
||||||
text={`Reputation: ${formattedRep}`}
|
getText={this.getReputationText}
|
||||||
tooltip={`You will earn ${numeralWrapper.format(favorGain, "0,0")} faction favor upon resetting after installing an Augmentation`}
|
getTooltip={this.getFavorGainText}
|
||||||
/>
|
/>
|
||||||
<p style={blockStyleMarkup}>-------------------------</p>
|
<p style={blockStyleMarkup}>-------------------------</p>
|
||||||
<ParagraphWithTooltip
|
<ParagraphWithTooltip
|
||||||
|
@ -158,14 +158,14 @@ export function makeRuntimeRejectMsg(workerScript, msg, exp=null) {
|
|||||||
//Run a script from inside a script using run() command
|
//Run a script from inside a script using run() command
|
||||||
export function runScriptFromScript(server, scriptname, args, workerScript, threads=1) {
|
export function runScriptFromScript(server, scriptname, args, workerScript, threads=1) {
|
||||||
//Check if the script is already running
|
//Check if the script is already running
|
||||||
var runningScriptObj = findRunningScript(scriptname, args, server);
|
let runningScriptObj = findRunningScript(scriptname, args, server);
|
||||||
if (runningScriptObj != null) {
|
if (runningScriptObj != null) {
|
||||||
workerScript.scriptRef.log(scriptname + " is already running on " + server.hostname);
|
workerScript.scriptRef.log(scriptname + " is already running on " + server.hostname);
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//'null/undefined' arguments are not allowed
|
//'null/undefined' arguments are not allowed
|
||||||
for (var i = 0; i < args.length; ++i) {
|
for (let i = 0; i < args.length; ++i) {
|
||||||
if (args[i] == null) {
|
if (args[i] == null) {
|
||||||
workerScript.scriptRef.log("ERROR: Cannot execute a script with null/undefined as an argument");
|
workerScript.scriptRef.log("ERROR: Cannot execute a script with null/undefined as an argument");
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
@ -191,10 +191,10 @@ export function runScriptFromScript(server, scriptname, args, workerScript, thre
|
|||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
} else {
|
} else {
|
||||||
//Able to run script
|
//Able to run script
|
||||||
if(workerScript.disableLogs.ALL == null && workerScript.disableLogs.exec == null && workerScript.disableLogs.run == null && workerScript.disableLogs.spawn == null) {
|
if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.exec == null && workerScript.disableLogs.run == null && workerScript.disableLogs.spawn == null) {
|
||||||
workerScript.scriptRef.log("Running script: " + scriptname + " on " + server.hostname + " with " + threads + " threads and args: " + arrayToString(args) + ". May take a few seconds to start up...");
|
workerScript.scriptRef.log(`Running script: ${scriptname} on ${server.hostname} with ${threads} threads and args: ${arrayToString(args)}. May take a few seconds to start up...`);
|
||||||
}
|
}
|
||||||
var runningScriptObj = new RunningScript(script, args);
|
let runningScriptObj = new RunningScript(script, args);
|
||||||
runningScriptObj.threads = threads;
|
runningScriptObj.threads = threads;
|
||||||
addWorkerScript(runningScriptObj, server);
|
addWorkerScript(runningScriptObj, server);
|
||||||
|
|
||||||
|
@ -3692,17 +3692,26 @@ function NetscriptFunctions(workerScript) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!factionExists(facname)) {
|
const fac = Factions[facname];
|
||||||
|
if (!(fac instanceof Faction)) {
|
||||||
workerScript.scriptRef.log("ERROR: getAugmentationsFromFaction() failed. Invalid faction name passed in (this is case-sensitive): " + facname);
|
workerScript.scriptRef.log("ERROR: getAugmentationsFromFaction() failed. Invalid faction name passed in (this is case-sensitive): " + facname);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var fac = Factions[facname];
|
// If player has a gang with this faction, return all factions
|
||||||
var res = [];
|
if (Player.hasGangWith(facname)) {
|
||||||
for (var i = 0; i < fac.augmentations.length; ++i) {
|
const res = [];
|
||||||
res.push(fac.augmentations[i]);
|
for (const augName in Augmentations) {
|
||||||
|
const aug = Augmentations[augName];
|
||||||
|
if (!aug.isSpecial) {
|
||||||
|
res.push(augName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
return fac.augmentations.slice();
|
||||||
},
|
},
|
||||||
getAugmentationPrereq : function(name) {
|
getAugmentationPrereq : function(name) {
|
||||||
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
|
var ramCost = CONSTANTS.ScriptSingularityFn3RamCost;
|
||||||
@ -3762,50 +3771,58 @@ function NetscriptFunctions(workerScript) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fac = Factions[faction];
|
const fac = Factions[faction];
|
||||||
if (fac == null || !(fac instanceof Faction)) {
|
if (!(fac instanceof Faction)) {
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because of invalid faction name: " + faction);
|
workerScript.log("ERROR: purchaseAugmentation() failed because of invalid faction name: " + faction);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fac.augmentations.includes(name)) {
|
let augs = [];
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because the faction " + faction + " does not contain the " + name + " augmentation");
|
if (Player.hasGangWith(faction)) {
|
||||||
|
for (const augName in Augmentations) {
|
||||||
|
const tempAug = Augmentations[augName];
|
||||||
|
if (!tempAug.isSpecial) {
|
||||||
|
augs.push(augName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
augs = fac.augmentations;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!augs.includes(name)) {
|
||||||
|
workerScript.log("ERROR: purchaseAugmentation() failed because the faction " + faction + " does not contain the " + name + " augmentation");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var aug = Augmentations[name];
|
const aug = Augmentations[name];
|
||||||
if (aug == null || !(aug instanceof Augmentation)) {
|
if (!(aug instanceof Augmentation)) {
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because of invalid augmentation name: " + name);
|
workerScript.log("ERROR: purchaseAugmentation() failed because of invalid augmentation name: " + name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isNeuroflux = false;
|
let isNeuroflux = (aug.name === AugmentationNames.NeuroFluxGovernor);
|
||||||
if (aug.name === AugmentationNames.NeuroFluxGovernor) {
|
|
||||||
isNeuroflux = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNeuroflux) {
|
if (!isNeuroflux) {
|
||||||
for (var j = 0; j < Player.queuedAugmentations.length; ++j) {
|
for (let j = 0; j < Player.queuedAugmentations.length; ++j) {
|
||||||
if (Player.queuedAugmentations[j].name === aug.name) {
|
if (Player.queuedAugmentations[j].name === aug.name) {
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you already have " + name);
|
workerScript.log("ERROR: purchaseAugmentation() failed because you already have " + name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var j = 0; j < Player.augmentations.length; ++j) {
|
for (let j = 0; j < Player.augmentations.length; ++j) {
|
||||||
if (Player.augmentations[j].name === aug.name) {
|
if (Player.augmentations[j].name === aug.name) {
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you already have " + name);
|
workerScript.log("ERROR: purchaseAugmentation() failed because you already have " + name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fac.playerReputation < aug.baseRepRequirement) {
|
if (fac.playerReputation < aug.baseRepRequirement) {
|
||||||
workerScript.scriptRef.log("ERROR: purchaseAugmentation() failed because you do not have enough reputation with " + fac.name);
|
workerScript.log("ERROR: purchaseAugmentation() failed because you do not have enough reputation with " + fac.name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = purchaseAugmentation(aug, fac, true);
|
var res = purchaseAugmentation(aug, fac, true);
|
||||||
workerScript.scriptRef.log(res);
|
workerScript.log(res);
|
||||||
if (isString(res) && res.startsWith("You purchased")) {
|
if (isString(res) && res.startsWith("You purchased")) {
|
||||||
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
||||||
return true;
|
return true;
|
||||||
|
@ -136,6 +136,7 @@ export interface IPlayer {
|
|||||||
getUpgradeHomeRamCost(): number;
|
getUpgradeHomeRamCost(): number;
|
||||||
gotoLocation(to: LocationName): boolean;
|
gotoLocation(to: LocationName): boolean;
|
||||||
hasCorporation(): boolean;
|
hasCorporation(): boolean;
|
||||||
|
hasGangWith(facName: string): boolean;
|
||||||
hasTorRouter(): boolean;
|
hasTorRouter(): boolean;
|
||||||
inBladeburner(): boolean;
|
inBladeburner(): boolean;
|
||||||
inGang(): boolean;
|
inGang(): boolean;
|
||||||
|
@ -23,7 +23,11 @@ export function getGangFaction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getGangName() {
|
export function getGangName() {
|
||||||
return this.gang.facName;
|
return this.inGang() ? this.gang.facName : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasGangWith(facName) {
|
||||||
|
return this.inGang() && this.gang.facName === facName;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function inGang() {
|
export function inGang() {
|
||||||
|
@ -424,7 +424,7 @@ function scriptCalculateOfflineProduction(runningScriptObj) {
|
|||||||
//designated server, and false otherwise
|
//designated server, and false otherwise
|
||||||
export function findRunningScript(filename, args, server) {
|
export function findRunningScript(filename, args, server) {
|
||||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||||
if (server.runningScripts[i].filename == filename &&
|
if (server.runningScripts[i].filename === filename &&
|
||||||
compareArrays(server.runningScripts[i].args, args)) {
|
compareArrays(server.runningScripts[i].args, args)) {
|
||||||
return server.runningScripts[i];
|
return server.runningScripts[i];
|
||||||
}
|
}
|
||||||
|
@ -206,6 +206,7 @@ export function stockMarketCycle() {
|
|||||||
if (stock.b) { thresh = 0.4; }
|
if (stock.b) { thresh = 0.4; }
|
||||||
if (Math.random() < thresh) {
|
if (Math.random() < thresh) {
|
||||||
stock.b = !stock.b;
|
stock.b = !stock.b;
|
||||||
|
if (stock.otlkMag < 10) { stock.otlkMag += 0.4; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@ import { Stock } from "./Stock";
|
|||||||
import { PositionTypes } from "./data/PositionTypes";
|
import { PositionTypes } from "./data/PositionTypes";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
|
// Amount by which a stock's forecast changes during each price movement
|
||||||
|
const forecastChangePerPriceMovement = 0.4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a stock, calculates the amount by which the stock price is multiplied
|
* Given a stock, calculates the amount by which the stock price is multiplied
|
||||||
* for an 'upward' price movement. This does not actually increase the stock's price,
|
* for an 'upward' price movement. This does not actually increase the stock's price,
|
||||||
@ -86,7 +89,7 @@ export function getBuyTransactionCost(stock: Stock, shares: number, posType: Pos
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a buy transaction's resulting price movement.
|
* Processes a buy transaction's resulting price AND forecast movement.
|
||||||
* @param {Stock} stock - Stock being purchased
|
* @param {Stock} stock - Stock being purchased
|
||||||
* @param {number} shares - Number of shares being transacted
|
* @param {number} shares - Number of shares being transacted
|
||||||
* @param {PositionTypes} posType - Long or short position
|
* @param {PositionTypes} posType - Long or short position
|
||||||
@ -125,6 +128,10 @@ export function processBuyTransactionPriceMovement(stock: Stock, shares: number,
|
|||||||
|
|
||||||
stock.price = currPrice;
|
stock.price = currPrice;
|
||||||
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
||||||
|
|
||||||
|
// Forecast always decreases in magnitude
|
||||||
|
const forecastChange = Math.min(5, forecastChangePerPriceMovement * numIterations);
|
||||||
|
stock.otlkMag -= forecastChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,6 +235,10 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
|
|||||||
|
|
||||||
stock.price = currPrice;
|
stock.price = currPrice;
|
||||||
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
||||||
|
|
||||||
|
// Forecast always decreases in magnitude
|
||||||
|
const forecastChange = Math.min(5, forecastChangePerPriceMovement * numIterations);
|
||||||
|
stock.otlkMag -= forecastChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +25,7 @@ export class StockTickerPositionText extends React.Component<IProps, any> {
|
|||||||
|
|
||||||
// Caculate total returns
|
// Caculate total returns
|
||||||
const totalCost = stock.playerShares * stock.playerAvgPx;
|
const totalCost = stock.playerShares * stock.playerAvgPx;
|
||||||
const gains = (stock.price - stock.playerAvgPx) * stock.playerShares;
|
const gains = (stock.getBidPrice() - stock.playerAvgPx) * stock.playerShares;
|
||||||
let percentageGains = gains / totalCost;
|
let percentageGains = gains / totalCost;
|
||||||
if (isNaN(percentageGains)) { percentageGains = 0; }
|
if (isNaN(percentageGains)) { percentageGains = 0; }
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ export class StockTickerPositionText extends React.Component<IProps, any> {
|
|||||||
|
|
||||||
// Caculate total returns
|
// Caculate total returns
|
||||||
const totalCost = stock.playerShortShares * stock.playerAvgShortPx;
|
const totalCost = stock.playerShortShares * stock.playerAvgShortPx;
|
||||||
const gains = (stock.playerAvgShortPx - stock.price) * stock.playerShortShares;
|
const gains = (stock.playerAvgShortPx - stock.getAskPrice()) * stock.playerShortShares;
|
||||||
let percentageGains = gains / totalCost;
|
let percentageGains = gains / totalCost;
|
||||||
if (isNaN(percentageGains)) { percentageGains = 0; }
|
if (isNaN(percentageGains)) { percentageGains = 0; }
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ import * as React from "react";
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
intervalTime?: number;
|
intervalTime?: number;
|
||||||
style?: object;
|
style?: object;
|
||||||
text: string;
|
getText: () => string;
|
||||||
tooltip?: string;
|
getTooltip?: () => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
@ -49,7 +49,14 @@ export class AutoupdatingParagraph extends React.Component<IProps, IState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const hasTooltip = this.props.tooltip != null && this.props.tooltip !== "";
|
let hasTooltip = this.props.getTooltip != null;
|
||||||
|
let tooltip: string | null;
|
||||||
|
if (hasTooltip) {
|
||||||
|
tooltip = this.props.getTooltip!();
|
||||||
|
if (tooltip === "") {
|
||||||
|
hasTooltip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const className = "tooltip";
|
const className = "tooltip";
|
||||||
|
|
||||||
@ -57,13 +64,13 @@ export class AutoupdatingParagraph extends React.Component<IProps, IState> {
|
|||||||
let tooltipMarkup: IInnerHTMLMarkup | null;
|
let tooltipMarkup: IInnerHTMLMarkup | null;
|
||||||
if (hasTooltip) {
|
if (hasTooltip) {
|
||||||
tooltipMarkup = {
|
tooltipMarkup = {
|
||||||
__html: this.props.tooltip!
|
__html: tooltip!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p className={className} style={this.props.style}>
|
<p className={className} style={this.props.style}>
|
||||||
{this.props.text}
|
{this.props.getText()}
|
||||||
{
|
{
|
||||||
hasTooltip &&
|
hasTooltip &&
|
||||||
<span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup!}></span>
|
<span className={"tooltiptext"} dangerouslySetInnerHTML={tooltipMarkup!}></span>
|
||||||
|
@ -9,11 +9,13 @@ export function arrayToString<T>(a: T[]) {
|
|||||||
const vals: any[] = [];
|
const vals: any[] = [];
|
||||||
for (let i = 0; i < a.length; ++i) {
|
for (let i = 0; i < a.length; ++i) {
|
||||||
let elem: any = a[i];
|
let elem: any = a[i];
|
||||||
if (typeof elem === "string") {
|
if (Array.isArray(elem)) {
|
||||||
|
elem = arrayToString(elem);
|
||||||
|
} else if (typeof elem === "string") {
|
||||||
elem = `"${elem}"`;
|
elem = `"${elem}"`;
|
||||||
}
|
}
|
||||||
vals.push(elem);
|
vals.push(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `[${vals.join(", ")}]`;
|
return `[${vals.join(", ")}]`;
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,19 @@ export function compareArrays<T>(a1: T[], a2: T[]) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i: number = 0; i < a1.length; ++i) {
|
for (let i = 0; i < a1.length; ++i) {
|
||||||
if (a1[i] !== a2[i]) {
|
if (Array.isArray(a1[i])) {
|
||||||
|
// If the other element is not an array, then these cannot be equal
|
||||||
|
if (!Array.isArray(a2[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elem1 = <any[]><any>a1[i];
|
||||||
|
const elem2 = <any[]><any>a2[i];
|
||||||
|
if (!compareArrays(elem1, elem2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (a1[i] !== a2[i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user