mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
Changed stock market price movements so that upward and downward movements use different trackers. Forecast can no longer be inverted due to price movements. Updated stock market unit tests
This commit is contained in:
parent
bd02e724e5
commit
94175877d7
@ -86,8 +86,11 @@ Sleeve memory dictates what a sleeve's synchronization will be when its reset by
|
||||
switching BitNodes. For example, if a sleeve has a memory of 10, then when you
|
||||
switch BitNodes its synchronization will initially be set to 10, rather than 1.
|
||||
|
||||
Memory can only be increased by purchasing upgrades from The Covenant.
|
||||
It is a persistent stat, meaning it never gets reset back to 1.
|
||||
Memory can only be increased by purchasing upgrades from The Covenant. Just like
|
||||
the ability to purchase additional sleeves, this is only available in BitNodes-10
|
||||
and above, and is only available after defeating BitNode-10 at least once.
|
||||
|
||||
Memory is a persistent stat, meaning it never gets reset back to 1.
|
||||
The maximum possible value for a sleeve's memory is 100.
|
||||
|
||||
Re-sleeving
|
||||
|
@ -21,4 +21,13 @@ hackAnalyzeThreads() Netscript Function
|
||||
If this function returns 50, this means that if your next `hack()` call
|
||||
is run on a script with 50 threads, it will steal $1m from the `foodnstuff` server.
|
||||
|
||||
**Warning**: The value returned by this function isn't necessarily a whole number.
|
||||
.. warning:: The value returned by this function isn't necessarily a whole number.
|
||||
.. warning:: It is possible for this function to return :code:`Infinity` or :code:`NaN` in
|
||||
certain uncommon scenarios. This is because in JavaScript:
|
||||
|
||||
* :code:`0 / 0 = NaN`
|
||||
* :code:`N / 0 = Infinity` for 0 < N < Infinity.
|
||||
|
||||
For example, if a server has no money available and you want to hack some positive
|
||||
amount from it, then the function would return :code:`Infinity` because
|
||||
this would be impossible.
|
||||
|
@ -279,7 +279,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
|
||||
{
|
||||
canPurchaseSleeves &&
|
||||
<Option
|
||||
buttonText={"Purchase Duplicate Sleeves"}
|
||||
buttonText={"Purchase & Upgrade Duplicate Sleeves"}
|
||||
infoText={sleevePurchasesInfo}
|
||||
onClick={this.sleevePurchases}
|
||||
/>
|
||||
|
@ -72,7 +72,7 @@ export function purchaseHacknet() {
|
||||
if (!Player.canAfford(cost)) { return -1; }
|
||||
Player.loseMoney(cost);
|
||||
const server = Player.createHacknetServer();
|
||||
Player.hashManager.updateCapacity(Player.hacknetNodes);
|
||||
updateHashManagerCapacity();
|
||||
|
||||
return numOwned;
|
||||
} else {
|
||||
@ -372,6 +372,8 @@ export function purchaseCacheUpgrade(node, levels=1) {
|
||||
|
||||
Player.loseMoney(cost);
|
||||
node.upgradeCache(sanitizedLevels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create/Refresh Hacknet Nodes UI
|
||||
|
@ -125,7 +125,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs) {
|
||||
|
||||
// We only execute limit orders until the price fails to match the order condition
|
||||
const isLong = (order.pos === PositionTypes.Long);
|
||||
const firstShares = Math.min(order.shares, stock.shareTxUntilMovement);
|
||||
const firstShares = Math.min(order.shares, isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown);
|
||||
|
||||
// First transaction to trigger movement
|
||||
let res = (isLong ? buyStock(stock, firstShares, null, opts) : shortStock(stock, firstShares, null, opts));
|
||||
@ -173,7 +173,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs) {
|
||||
if (totalShares === 0) {
|
||||
return; // Player has no shares
|
||||
}
|
||||
const firstShares = Math.min(totalShares, stock.shareTxUntilMovement);
|
||||
const firstShares = Math.min(totalShares, isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp);
|
||||
|
||||
// First transaction to trigger movement
|
||||
if (isLong ? sellStock(stock, firstShares, null, opts) : sellShort(stock, firstShares, null, opts)) {
|
||||
|
@ -138,8 +138,10 @@ export class Stock {
|
||||
|
||||
/**
|
||||
* How many share transactions remaining until a price movement occurs
|
||||
* (separately tracked for upward and downward movements)
|
||||
*/
|
||||
shareTxUntilMovement: number;
|
||||
shareTxUntilMovementDown: number;
|
||||
shareTxUntilMovementUp: number;
|
||||
|
||||
/**
|
||||
* Spread percentage. The bid/ask prices for this stock are N% above or below
|
||||
@ -160,22 +162,23 @@ export class Stock {
|
||||
readonly totalShares: number;
|
||||
|
||||
constructor(p: IConstructorParams = defaultConstructorParams) {
|
||||
this.name = p.name;
|
||||
this.symbol = p.symbol;
|
||||
this.price = toNumber(p.initPrice);
|
||||
this.lastPrice = this.price;
|
||||
this.playerShares = 0;
|
||||
this.playerAvgPx = 0;
|
||||
this.playerShortShares = 0;
|
||||
this.playerAvgShortPx = 0;
|
||||
this.mv = toNumber(p.mv);
|
||||
this.b = p.b;
|
||||
this.otlkMag = p.otlkMag;
|
||||
this.cap = getRandomInt(this.price * 1e3, this.price * 25e3);
|
||||
this.spreadPerc = toNumber(p.spreadPerc);
|
||||
this.priceMovementPerc = this.spreadPerc / (getRandomInt(10, 30) / 10);
|
||||
this.shareTxForMovement = toNumber(p.shareTxForMovement);
|
||||
this.shareTxUntilMovement = this.shareTxForMovement;
|
||||
this.name = p.name;
|
||||
this.symbol = p.symbol;
|
||||
this.price = toNumber(p.initPrice);
|
||||
this.lastPrice = this.price;
|
||||
this.playerShares = 0;
|
||||
this.playerAvgPx = 0;
|
||||
this.playerShortShares = 0;
|
||||
this.playerAvgShortPx = 0;
|
||||
this.mv = toNumber(p.mv);
|
||||
this.b = p.b;
|
||||
this.otlkMag = p.otlkMag;
|
||||
this.cap = getRandomInt(this.price * 1e3, this.price * 25e3);
|
||||
this.spreadPerc = toNumber(p.spreadPerc);
|
||||
this.priceMovementPerc = this.spreadPerc / (getRandomInt(10, 30) / 10);
|
||||
this.shareTxForMovement = toNumber(p.shareTxForMovement);
|
||||
this.shareTxUntilMovementDown = this.shareTxForMovement;
|
||||
this.shareTxUntilMovementUp = this.shareTxForMovement;
|
||||
|
||||
// Total shares is determined by market cap, and is rounded to nearest 100k
|
||||
let totalSharesUnrounded: number = (p.marketCap / this.price);
|
||||
|
@ -279,7 +279,8 @@ export function processStockPrices(numCycles=1) {
|
||||
}
|
||||
|
||||
// Shares required for price movement gradually approaches max over time
|
||||
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 5, stock.shareTxForMovement);
|
||||
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovementUp + 5, stock.shareTxForMovement);
|
||||
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovementDown + 5, stock.shareTxForMovement);
|
||||
}
|
||||
|
||||
displayStockMarketContent();
|
||||
|
@ -3,7 +3,7 @@ import { PositionTypes } from "./data/PositionTypes";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
// Amount by which a stock's forecast changes during each price movement
|
||||
export const forecastChangePerPriceMovement = 0.05;
|
||||
export const forecastChangePerPriceMovement = 0.1;
|
||||
|
||||
/**
|
||||
* Given a stock, calculates the amount by which the stock price is multiplied
|
||||
@ -49,21 +49,24 @@ export function getBuyTransactionCost(stock: Stock, shares: number, posType: Pos
|
||||
const isLong = (posType === PositionTypes.Long);
|
||||
|
||||
// If the number of shares doesn't trigger a price movement, its a simple calculation
|
||||
if (shares <= stock.shareTxUntilMovement) {
|
||||
if (isLong) {
|
||||
if (isLong) {
|
||||
if (shares <= stock.shareTxUntilMovementUp) {
|
||||
return (shares * stock.getAskPrice()) + CONSTANTS.StockMarketCommission;
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
if (shares <= stock.shareTxUntilMovementDown) {
|
||||
return (shares * stock.getBidPrice()) + CONSTANTS.StockMarketCommission;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate how many iterations of price changes we need to account for
|
||||
let remainingShares = shares - stock.shareTxUntilMovement;
|
||||
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
|
||||
let remainingShares = shares - firstShares;
|
||||
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
|
||||
|
||||
// The initial cost calculation takes care of the first "iteration"
|
||||
let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();
|
||||
let totalCost = (stock.shareTxUntilMovement * currPrice);
|
||||
let totalCost = (firstShares * currPrice);
|
||||
|
||||
const increasingMvmt = calculateIncreasingPriceMovement(stock)!;
|
||||
const decreasingMvmt = calculateDecreasingPriceMovement(stock)!;
|
||||
@ -111,42 +114,66 @@ export function processBuyTransactionPriceMovement(stock: Stock, shares: number,
|
||||
}
|
||||
}
|
||||
|
||||
// No price/forecast movement
|
||||
if (shares <= stock.shareTxUntilMovement) {
|
||||
stock.shareTxUntilMovement -= shares;
|
||||
if (stock.shareTxUntilMovement <= 0) {
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
// If there's only going to be one iteration
|
||||
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
|
||||
if (shares <= firstShares) {
|
||||
function triggerMovement() {
|
||||
processPriceMovement();
|
||||
stock.changePrice(currPrice);
|
||||
stock.otlkMag -= (forecastChangePerPriceMovement);
|
||||
}
|
||||
|
||||
if (isLong) {
|
||||
stock.shareTxUntilMovementUp -= shares;
|
||||
if (stock.shareTxUntilMovementUp <= 0) {
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
|
||||
triggerMovement();
|
||||
}
|
||||
} else {
|
||||
stock.shareTxUntilMovementDown -= shares;
|
||||
if (stock.shareTxUntilMovementDown <= 0) {
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
|
||||
triggerMovement();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate how many iterations of price changes we need to account for
|
||||
let remainingShares = shares - stock.shareTxUntilMovement;
|
||||
let remainingShares = shares - firstShares;
|
||||
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
|
||||
|
||||
for (let i = 1; i < numIterations; ++i) {
|
||||
processPriceMovement();
|
||||
}
|
||||
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {
|
||||
// The shareTxUntilMovement ended up at 0 at the end of the "processing"
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
// If on the offchance we end up perfectly at the next price movement
|
||||
if (isLong) {
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementUp) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovementUp === stock.shareTxForMovement || stock.shareTxUntilMovementUp <= 0) {
|
||||
// The shareTxUntilMovementUp ended up at 0 at the end of the "processing"
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
} else {
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementDown) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovementDown === stock.shareTxForMovement || stock.shareTxUntilMovementDown <= 0) {
|
||||
// The shareTxUntilMovementDown ended up at 0 at the end of the "processing"
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
}
|
||||
|
||||
stock.changePrice(currPrice);
|
||||
|
||||
// Forecast always decreases in magnitude
|
||||
const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));
|
||||
stock.otlkMag -= forecastChange;
|
||||
if (stock.otlkMag < 0) {
|
||||
stock.b = !stock.b;
|
||||
stock.otlkMag = Math.abs(stock.otlkMag);
|
||||
if (stock.otlkMag < 0.1) {
|
||||
stock.otlkMag = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,9 +193,10 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
|
||||
shares = Math.min(shares, stock.maxShares);
|
||||
|
||||
const isLong = (posType === PositionTypes.Long);
|
||||
const firstShares = isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
|
||||
|
||||
// If the number of shares doesn't trigger a price mvoement, its a simple calculation
|
||||
if (shares <= stock.shareTxUntilMovement) {
|
||||
if (shares <= firstShares) {
|
||||
if (isLong) {
|
||||
return (shares * stock.getBidPrice()) - CONSTANTS.StockMarketCommission;
|
||||
} else {
|
||||
@ -181,7 +209,7 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
|
||||
}
|
||||
|
||||
// Calculate how many iterations of price changes we need to account for
|
||||
let remainingShares = shares - stock.shareTxUntilMovement;
|
||||
let remainingShares = shares - firstShares;
|
||||
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
|
||||
|
||||
// Helper function to calculate gain for a single iteration
|
||||
@ -198,7 +226,7 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
|
||||
|
||||
// The initial cost calculation takes care of the first "iteration"
|
||||
let currPrice = isLong ? stock.getBidPrice() : stock.getAskPrice();
|
||||
let totalGain = calculateGain(currPrice, stock.shareTxUntilMovement);
|
||||
let totalGain = calculateGain(currPrice, firstShares);
|
||||
for (let i = 1; i < numIterations; ++i) {
|
||||
// Price movement
|
||||
if (isLong) {
|
||||
@ -229,6 +257,7 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
|
||||
shares = Math.min(shares, stock.maxShares);
|
||||
|
||||
const isLong = (posType === PositionTypes.Long);
|
||||
const firstShares = isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
|
||||
|
||||
let currPrice = stock.price;
|
||||
function processPriceMovement() {
|
||||
@ -239,41 +268,64 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
|
||||
}
|
||||
}
|
||||
|
||||
// No price/forecast movement
|
||||
if (shares <= stock.shareTxUntilMovement) {
|
||||
stock.shareTxUntilMovement -= shares;
|
||||
if (stock.shareTxUntilMovement <= 0) {
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
// If there's only going to be one iteration at most
|
||||
if (shares <= firstShares) {
|
||||
function triggerPriceMovement() {
|
||||
processPriceMovement();
|
||||
stock.changePrice(currPrice);
|
||||
stock.otlkMag -= (forecastChangePerPriceMovement);
|
||||
}
|
||||
|
||||
if (isLong) {
|
||||
stock.shareTxUntilMovementDown -= shares;
|
||||
if (stock.shareTxUntilMovementDown <= 0) {
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
|
||||
triggerPriceMovement();
|
||||
}
|
||||
} else {
|
||||
stock.shareTxUntilMovementUp -= shares;
|
||||
if (stock.shareTxUntilMovementUp <= 0) {
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
|
||||
triggerPriceMovement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate how many iterations of price changes we need to account for
|
||||
let remainingShares = shares - stock.shareTxUntilMovement;
|
||||
let remainingShares = shares - firstShares;
|
||||
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
|
||||
|
||||
for (let i = 1; i < numIterations; ++i) {
|
||||
processPriceMovement();
|
||||
}
|
||||
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
// If on the offchance we end up perfectly at the next price movement
|
||||
if (isLong) {
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementDown) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovementDown === stock.shareTxForMovement || stock.shareTxUntilMovementDown <= 0) {
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
} else {
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementUp) % stock.shareTxForMovement);
|
||||
if (stock.shareTxUntilMovementUp === stock.shareTxForMovement || stock.shareTxUntilMovementUp <= 0) {
|
||||
++numIterations;
|
||||
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
}
|
||||
|
||||
stock.changePrice(currPrice);
|
||||
|
||||
// Forecast always decreases in magnitude
|
||||
const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));
|
||||
stock.otlkMag -= forecastChange;
|
||||
if (stock.otlkMag < 0) {
|
||||
stock.b = !stock.b;
|
||||
stock.otlkMag = Math.abs(stock.otlkMag);
|
||||
if (stock.otlkMag < 0.1) {
|
||||
stock.otlkMag = 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,14 +351,15 @@ export function calculateBuyMaxAmount(stock: Stock, posType: PositionTypes, mone
|
||||
let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();
|
||||
|
||||
// No price movement
|
||||
const firstIterationCost = stock.shareTxUntilMovement * currPrice;
|
||||
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
|
||||
const firstIterationCost = firstShares * currPrice;
|
||||
if (remainingMoney < firstIterationCost) {
|
||||
return Math.floor(remainingMoney / currPrice);
|
||||
}
|
||||
|
||||
// We'll avoid any accidental infinite loops by having a hardcoded maximum number of
|
||||
// iterations
|
||||
let numShares = stock.shareTxUntilMovement;
|
||||
let numShares = firstShares;
|
||||
remainingMoney -= firstIterationCost;
|
||||
for (let i = 0; i < 10e3; ++i) {
|
||||
if (isLong) {
|
||||
|
@ -48,6 +48,7 @@ type IProps = {
|
||||
orders: Order[];
|
||||
p: IPlayer;
|
||||
placeOrder: placeOrderFn;
|
||||
rerenderAllTickers: () => void;
|
||||
sellStockLong: txFn;
|
||||
sellStockShort: txFn;
|
||||
stock: Stock;
|
||||
@ -57,7 +58,6 @@ type IState = {
|
||||
orderType: SelectorOrderType;
|
||||
position: PositionTypes;
|
||||
qty: string;
|
||||
rerenderFlag: boolean;
|
||||
}
|
||||
|
||||
export class StockTicker extends React.Component<IProps, IState> {
|
||||
@ -68,7 +68,6 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
orderType: SelectorOrderType.Market,
|
||||
position: PositionTypes.Long,
|
||||
qty: "",
|
||||
rerenderFlag: false,
|
||||
}
|
||||
|
||||
this.getBuyTransactionCostText = this.getBuyTransactionCostText.bind(this);
|
||||
@ -81,7 +80,6 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
this.handleQuantityChange = this.handleQuantityChange.bind(this);
|
||||
this.handleSellButtonClick = this.handleSellButtonClick.bind(this);
|
||||
this.handleSellAllButtonClick = this.handleSellAllButtonClick.bind(this);
|
||||
this.rerender = this.rerender.bind(this);
|
||||
}
|
||||
|
||||
createPlaceOrderPopupBox(yesTxt: string, popupTxt: string, yesBtnCb: (price: number) => void) {
|
||||
@ -119,7 +117,8 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
let costTxt = `Purchasing ${numeralWrapper.formatBigNumber(qty)} shares (${this.state.position === PositionTypes.Long ? "Long" : "Short"}) ` +
|
||||
`will cost ${numeralWrapper.formatMoney(cost)}. `;
|
||||
|
||||
const causesMovement = qty > stock.shareTxUntilMovement;
|
||||
const amtNeededForMovement = this.state.position === PositionTypes.Long ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
|
||||
const causesMovement = qty > amtNeededForMovement;
|
||||
if (causesMovement) {
|
||||
costTxt += `WARNING: Purchasing this many shares will influence the stock price`;
|
||||
}
|
||||
@ -152,7 +151,8 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
let costTxt = `Selling ${numeralWrapper.formatBigNumber(qty)} shares (${this.state.position === PositionTypes.Long ? "Long" : "Short"}) ` +
|
||||
`will result in a gain of ${numeralWrapper.formatMoney(cost)}. `;
|
||||
|
||||
const causesMovement = qty > stock.shareTxUntilMovement;
|
||||
const amtNeededForMovement = this.state.position === PositionTypes.Long ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
|
||||
const causesMovement = qty > amtNeededForMovement;
|
||||
if (causesMovement) {
|
||||
costTxt += `WARNING: Selling this many shares will influence the stock price`;
|
||||
}
|
||||
@ -174,7 +174,7 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
} else {
|
||||
this.props.buyStockLong(this.props.stock, shares);
|
||||
}
|
||||
this.rerender();
|
||||
this.props.rerenderAllTickers();
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Limit: {
|
||||
@ -216,7 +216,7 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
} else {
|
||||
this.props.buyStockLong(stock, maxShares);
|
||||
}
|
||||
this.rerender();
|
||||
this.props.rerenderAllTickers();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -297,7 +297,7 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
} else {
|
||||
this.props.sellStockLong(this.props.stock, shares);
|
||||
}
|
||||
this.rerender();
|
||||
this.props.rerenderAllTickers();
|
||||
break;
|
||||
}
|
||||
case SelectorOrderType.Limit: {
|
||||
@ -335,7 +335,7 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
} else {
|
||||
this.props.sellStockLong(stock, stock.playerShares);
|
||||
}
|
||||
this.rerender();
|
||||
this.props.rerenderAllTickers();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -355,20 +355,12 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
return (this.props.p.bitNodeN === 8 || (SourceFileFlags[8] >= 2));
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
// Determine if the player's intended transaction will cause a price movement
|
||||
let causesMovement: boolean = false;
|
||||
const qty = this.getQuantity();
|
||||
if (!isNaN(qty)) {
|
||||
causesMovement = qty > this.props.stock.shareTxUntilMovement;
|
||||
causesMovement = qty > this.props.stock.shareTxForMovement;
|
||||
}
|
||||
|
||||
return (
|
||||
@ -411,7 +403,7 @@ export class StockTicker extends React.Component<IProps, IState> {
|
||||
{
|
||||
causesMovement &&
|
||||
<p className="stock-market-price-movement-warning">
|
||||
WARNING: Buying/Selling {numeralWrapper.formatBigNumber(qty)} shares will affect
|
||||
WARNING: Buying/Selling {numeralWrapper.formatBigNumber(qty)} shares may affect
|
||||
the stock's price. This applies during the transaction itself as well. See Investopedia
|
||||
for more details.
|
||||
</p>
|
||||
|
@ -53,6 +53,7 @@ export class StockTickers extends React.Component<IProps, IState> {
|
||||
this.changeWatchlistFilter = this.changeWatchlistFilter.bind(this);
|
||||
this.collapseAllTickers = this.collapseAllTickers.bind(this);
|
||||
this.expandAllTickers = this.expandAllTickers.bind(this);
|
||||
this.rerender = this.rerender.bind(this);
|
||||
|
||||
this.listRef = React.createRef();
|
||||
}
|
||||
@ -159,6 +160,7 @@ export class StockTickers extends React.Component<IProps, IState> {
|
||||
orders={orders}
|
||||
p={this.props.p}
|
||||
placeOrder={this.props.placeOrder}
|
||||
rerenderAllTickers={this.rerender}
|
||||
sellStockLong={this.props.sellStockLong}
|
||||
sellStockShort={this.props.sellStockShort}
|
||||
stock={val}
|
||||
|
@ -52,16 +52,17 @@ export function displayCharacterInfo(elem: HTMLElement, p: IPlayer) {
|
||||
|
||||
function convertMoneySourceTrackerToString(src: MoneySourceTracker): string {
|
||||
let parts: string[] = [`Total: ${numeralWrapper.formatMoney(src.total)}`];
|
||||
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
|
||||
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
|
||||
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
|
||||
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
|
||||
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
|
||||
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
|
||||
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
|
||||
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
|
||||
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
|
||||
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
|
||||
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
|
||||
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
|
||||
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
|
||||
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
|
||||
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
|
||||
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
|
||||
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
|
||||
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
|
||||
if (src.hospitalization) { parts.push(`Hospitalization: ${numeralWrapper.formatMoney(src.hospitalization)}`) };
|
||||
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
|
||||
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
|
||||
|
||||
return parts.join("<br>");
|
||||
}
|
||||
|
@ -79,7 +79,8 @@ describe("Stock Market Tests", function() {
|
||||
expect(stock.b).to.equal(ctorParams.b);
|
||||
expect(stock.mv).to.equal(ctorParams.mv);
|
||||
expect(stock.shareTxForMovement).to.equal(ctorParams.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovement).to.equal(ctorParams.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(ctorParams.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(ctorParams.shareTxForMovement);
|
||||
expect(stock.maxShares).to.be.below(stock.totalShares);
|
||||
expect(stock.spreadPerc).to.equal(ctorParams.spreadPerc);
|
||||
expect(stock.priceMovementPerc).to.be.a("number");
|
||||
@ -436,24 +437,24 @@ describe("Stock Market Tests", function() {
|
||||
|
||||
it("should do nothing on invalid 'stock' argument", function() {
|
||||
const oldPrice = stock.price;
|
||||
const oldTracker = stock.shareTxUntilMovement;
|
||||
const oldTracker = stock.shareTxUntilMovementUp;
|
||||
|
||||
processBuyTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
|
||||
});
|
||||
|
||||
it("should do nothing on invalid 'shares' arg", function() {
|
||||
const oldPrice = stock.price;
|
||||
const oldTracker = stock.shareTxUntilMovement;
|
||||
const oldTracker = stock.shareTxUntilMovementUp;
|
||||
|
||||
processBuyTransactionPriceMovement(stock, NaN, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
|
||||
|
||||
processBuyTransactionPriceMovement(stock, -1, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
|
||||
});
|
||||
|
||||
it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() {
|
||||
@ -463,7 +464,8 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.otlkMag).to.equal(oldForecast);
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() {
|
||||
@ -473,7 +475,8 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.otlkMag).to.equal(oldForecast);
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that trigger price movements", function() {
|
||||
@ -483,7 +486,7 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that trigger price movements", function() {
|
||||
@ -493,7 +496,7 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() {
|
||||
@ -503,7 +506,8 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() {
|
||||
@ -511,10 +515,11 @@ describe("Stock Market Tests", function() {
|
||||
const oldForecast = stock.otlkMag;
|
||||
|
||||
processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovementUp, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() {
|
||||
@ -524,7 +529,8 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() {
|
||||
@ -534,7 +540,8 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() {
|
||||
@ -542,10 +549,11 @@ describe("Stock Market Tests", function() {
|
||||
const oldForecast = stock.otlkMag;
|
||||
|
||||
processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);
|
||||
expect(stock.shareTxUntilMovementDown).to.be.below(stock.shareTxForMovement);
|
||||
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovementDown, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() {
|
||||
@ -555,7 +563,7 @@ describe("Stock Market Tests", function() {
|
||||
processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
});
|
||||
|
||||
@ -565,24 +573,24 @@ describe("Stock Market Tests", function() {
|
||||
|
||||
it("should do nothing on invalid 'stock' argument", function() {
|
||||
const oldPrice = stock.price;
|
||||
const oldTracker = stock.shareTxUntilMovement;
|
||||
const oldTracker = stock.shareTxUntilMovementDown;
|
||||
|
||||
processSellTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
|
||||
});
|
||||
|
||||
it("should do nothing on invalid 'shares' arg", function() {
|
||||
const oldPrice = stock.price;
|
||||
const oldTracker = stock.shareTxUntilMovement;
|
||||
const oldTracker = stock.shareTxUntilMovementDown;
|
||||
|
||||
processSellTransactionPriceMovement(stock, NaN, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
|
||||
|
||||
processSellTransactionPriceMovement(stock, -1, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
|
||||
});
|
||||
|
||||
it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() {
|
||||
@ -592,7 +600,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.otlkMag).to.equal(oldForecast);
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() {
|
||||
@ -602,7 +611,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(oldPrice);
|
||||
expect(stock.otlkMag).to.equal(oldForecast);
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that trigger price movements", function() {
|
||||
@ -612,7 +622,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that trigger price movements", function() {
|
||||
@ -622,7 +633,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() {
|
||||
@ -632,7 +644,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() {
|
||||
@ -640,10 +653,12 @@ describe("Stock Market Tests", function() {
|
||||
const oldForecast = stock.otlkMag;
|
||||
|
||||
processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);
|
||||
expect(stock.shareTxUntilMovementDown).to.be.below(stock.shareTxForMovement);
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovementDown, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() {
|
||||
@ -653,7 +668,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);
|
||||
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() {
|
||||
@ -663,7 +679,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() {
|
||||
@ -671,10 +688,13 @@ describe("Stock Market Tests", function() {
|
||||
const oldForecast = stock.otlkMag;
|
||||
|
||||
processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);
|
||||
expect(stock.shareTxUntilMovementUp).to.be.below(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovementUp, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
|
||||
it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() {
|
||||
@ -684,7 +704,8 @@ describe("Stock Market Tests", function() {
|
||||
processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);
|
||||
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
|
||||
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
|
||||
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
|
||||
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user