STOCKMARKET: Move and Reorganize Constants (#688)

This commit is contained in:
Caldwell 2023-08-01 04:12:49 +02:00 committed by GitHub
parent e9bbe57902
commit a85efbc4da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 49 additions and 53 deletions

@ -31,11 +31,6 @@ export const CONSTANTS: {
PurchasedServerMaxRam: number; PurchasedServerMaxRam: number;
MultipleAugMultiplier: number; MultipleAugMultiplier: number;
TorRouterCost: number; TorRouterCost: number;
WSEAccountCost: number;
TIXAPICost: number;
MarketData4SCost: number;
MarketDataTixApi4SCost: number;
StockMarketCommission: number;
HospitalCostPerHp: number; HospitalCostPerHp: number;
IntelligenceCrimeWeight: number; IntelligenceCrimeWeight: number;
IntelligenceInfiltrationWeight: number; IntelligenceInfiltrationWeight: number;
@ -140,13 +135,6 @@ export const CONSTANTS: {
// TOR Router // TOR Router
TorRouterCost: 200e3, TorRouterCost: 200e3,
// Stock market
WSEAccountCost: 200e6,
TIXAPICost: 5e9,
MarketData4SCost: 1e9,
MarketDataTixApi4SCost: 25e9,
StockMarketCommission: 100e3,
// Hospital/Health // Hospital/Health
HospitalCostPerHp: 100e3, HospitalCostPerHp: 100e3,

@ -11,7 +11,7 @@ import {
import { PositionType } from "@enums"; import { PositionType } from "@enums";
import { CONSTANTS } from "../Constants"; import { StockMarketConstants } from "./data/Constants";
import { Player } from "@player"; import { Player } from "@player";
import { formatMoney, formatShares } from "../ui/formatNumber"; import { formatMoney, formatShares } from "../ui/formatNumber";
@ -103,7 +103,7 @@ export function buyStock(
const origTotal = stock.playerShares * stock.playerAvgPx; const origTotal = stock.playerShares * stock.playerAvgPx;
Player.loseMoney(totalPrice, "stock"); Player.loseMoney(totalPrice, "stock");
const newTotal = origTotal + totalPrice - CONSTANTS.StockMarketCommission; const newTotal = origTotal + totalPrice - StockMarketConstants.StockMarketCommission;
stock.playerShares = Math.round(stock.playerShares + shares); stock.playerShares = Math.round(stock.playerShares + shares);
stock.playerAvgPx = newTotal / stock.playerShares; stock.playerAvgPx = newTotal / stock.playerShares;
processTransactionForecastMovement(stock, shares); processTransactionForecastMovement(stock, shares);
@ -114,13 +114,13 @@ export function buyStock(
if (ctx) { if (ctx) {
const resultTxt = `Bought ${formatShares(shares)} shares of ${stock.symbol} for ${formatMoney( const resultTxt = `Bought ${formatShares(shares)} shares of ${stock.symbol} for ${formatMoney(
totalPrice, totalPrice,
)}. Paid ${formatMoney(CONSTANTS.StockMarketCommission)} in commission fees.`; )}. Paid ${formatMoney(StockMarketConstants.StockMarketCommission)} in commission fees.`;
helpers.log(ctx, () => resultTxt); helpers.log(ctx, () => resultTxt);
} else if (opts.suppressDialog !== true) { } else if (opts.suppressDialog !== true) {
dialogBoxCreate( dialogBoxCreate(
<> <>
Bought {formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />. Paid{" "} Bought {formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />. Paid{" "}
<Money money={CONSTANTS.StockMarketCommission} /> in commission fees. <Money money={StockMarketConstants.StockMarketCommission} /> in commission fees.
</>, </>,
); );
} }
@ -278,7 +278,7 @@ export function shortStock(
const origTotal = stock.playerShortShares * stock.playerAvgShortPx; const origTotal = stock.playerShortShares * stock.playerAvgShortPx;
Player.loseMoney(totalPrice, "stock"); Player.loseMoney(totalPrice, "stock");
const newTotal = origTotal + totalPrice - CONSTANTS.StockMarketCommission; const newTotal = origTotal + totalPrice - StockMarketConstants.StockMarketCommission;
stock.playerShortShares = Math.round(stock.playerShortShares + shares); stock.playerShortShares = Math.round(stock.playerShortShares + shares);
stock.playerAvgShortPx = newTotal / stock.playerShortShares; stock.playerAvgShortPx = newTotal / stock.playerShortShares;
processTransactionForecastMovement(stock, shares); processTransactionForecastMovement(stock, shares);
@ -290,14 +290,14 @@ export function shortStock(
if (ctx) { if (ctx) {
const resultTxt = const resultTxt =
`Bought a short position of ${formatShares(shares)} shares of ${stock.symbol} ` + `Bought a short position of ${formatShares(shares)} shares of ${stock.symbol} ` +
`for ${formatMoney(totalPrice)}. Paid ${formatMoney(CONSTANTS.StockMarketCommission)} ` + `for ${formatMoney(totalPrice)}. Paid ${formatMoney(StockMarketConstants.StockMarketCommission)} ` +
`in commission fees.`; `in commission fees.`;
helpers.log(ctx, () => resultTxt); helpers.log(ctx, () => resultTxt);
} else if (!opts.suppressDialog) { } else if (!opts.suppressDialog) {
dialogBoxCreate( dialogBoxCreate(
<> <>
Bought a short position of {formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />. Bought a short position of {formatShares(shares)} shares of {stock.symbol} for <Money money={totalPrice} />.
Paid <Money money={CONSTANTS.StockMarketCommission} /> in commission fees. Paid <Money money={StockMarketConstants.StockMarketCommission} /> in commission fees.
</>, </>,
); );
} }

@ -1,9 +1,9 @@
import type { IOrderBook } from "./IOrderBook"; import type { IOrderBook } from "./IOrderBook";
import type { IStockMarket } from "./IStockMarket"; import type { IStockMarket } from "./IStockMarket";
import { Order } from "./Order"; import { Order } from "./Order";
import { StockMarketConstants } from "./data/Constants";
import { processOrders } from "./OrderProcessing"; import { processOrders } from "./OrderProcessing";
import { Stock } from "./Stock"; import { Stock } from "./Stock";
import { TicksPerCycle } from "./StockMarketConstants";
import { InitStockMetadata } from "./data/InitStockMetadata"; import { InitStockMetadata } from "./data/InitStockMetadata";
import { PositionType, OrderType, StockSymbol } from "@enums"; import { PositionType, OrderType, StockSymbol } from "@enums";
@ -165,7 +165,7 @@ export function initStockMarket(): void {
StockMarket.storedCycles = 0; StockMarket.storedCycles = 0;
StockMarket.lastUpdate = 0; StockMarket.lastUpdate = 0;
StockMarket.ticksUntilCycle = TicksPerCycle; StockMarket.ticksUntilCycle = StockMarketConstants.TicksPerCycle;
initSymbolToStockMap(); initSymbolToStockMap();
} }
@ -191,13 +191,11 @@ function stockMarketCycle(): void {
stock.flipForecastForecast(); stock.flipForecastForecast();
} }
StockMarket.ticksUntilCycle = TicksPerCycle; StockMarket.ticksUntilCycle = StockMarketConstants.TicksPerCycle;
} }
} }
// Stock prices updated every 6 seconds const cyclesPerStockUpdate = StockMarketConstants.msPerStockUpdate / CONSTANTS.MilliPerCycle;
const msPerStockUpdate = 6e3;
const cyclesPerStockUpdate = msPerStockUpdate / CONSTANTS.MilliPerCycle;
export function processStockPrices(numCycles = 1): void { export function processStockPrices(numCycles = 1): void {
if (StockMarket.storedCycles == null || isNaN(StockMarket.storedCycles)) { if (StockMarket.storedCycles == null || isNaN(StockMarket.storedCycles)) {
StockMarket.storedCycles = 0; StockMarket.storedCycles = 0;
@ -211,14 +209,14 @@ export function processStockPrices(numCycles = 1): void {
// We can process the update every 4 seconds as long as there are enough // We can process the update every 4 seconds as long as there are enough
// stored cycles. This lets us account for offline time // stored cycles. This lets us account for offline time
const timeNow = new Date().getTime(); const timeNow = new Date().getTime();
if (timeNow - StockMarket.lastUpdate < 4e3) return; if (timeNow - StockMarket.lastUpdate < StockMarketConstants.msPerStockUpdateMin) return;
StockMarket.lastUpdate = timeNow; StockMarket.lastUpdate = timeNow;
StockMarket.storedCycles -= cyclesPerStockUpdate; StockMarket.storedCycles -= cyclesPerStockUpdate;
// Cycle // Cycle
if (StockMarket.ticksUntilCycle == null || typeof StockMarket.ticksUntilCycle !== "number") { if (StockMarket.ticksUntilCycle == null || typeof StockMarket.ticksUntilCycle !== "number") {
StockMarket.ticksUntilCycle = TicksPerCycle; StockMarket.ticksUntilCycle = StockMarketConstants.TicksPerCycle;
} }
--StockMarket.ticksUntilCycle; --StockMarket.ticksUntilCycle;
if (StockMarket.ticksUntilCycle <= 0) stockMarketCycle(); if (StockMarket.ticksUntilCycle <= 0) stockMarketCycle();

@ -1,5 +0,0 @@
/**
* How many stock market 'ticks' before a 'cycle' is triggered.
* A 'tick' is whenever stock prices update
*/
export const TicksPerCycle = 75;

@ -1,18 +1,18 @@
import { currentNodeMults } from "../BitNode/BitNodeMultipliers"; import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants"; import { StockMarketConstants } from "./data/Constants";
export function getStockMarket4SDataCost(): number { export function getStockMarket4SDataCost(): number {
return CONSTANTS.MarketData4SCost * currentNodeMults.FourSigmaMarketDataCost; return StockMarketConstants.MarketData4SCost * currentNodeMults.FourSigmaMarketDataCost;
} }
export function getStockMarket4STixApiCost(): number { export function getStockMarket4STixApiCost(): number {
return CONSTANTS.MarketDataTixApi4SCost * currentNodeMults.FourSigmaMarketDataApiCost; return StockMarketConstants.MarketDataTixApi4SCost * currentNodeMults.FourSigmaMarketDataApiCost;
} }
export function getStockMarketWseCost(): number { export function getStockMarketWseCost(): number {
return CONSTANTS.WSEAccountCost; return StockMarketConstants.WSEAccountCost;
} }
export function getStockMarketTixApiCost(): number { export function getStockMarketTixApiCost(): number {
return CONSTANTS.TIXAPICost; return StockMarketConstants.TIXAPICost;
} }

@ -1,6 +1,6 @@
import { Stock } from "./Stock"; import { Stock } from "./Stock";
import { PositionType } from "@enums"; import { PositionType } from "@enums";
import { CONSTANTS } from "../Constants"; import { StockMarketConstants } from "./data/Constants";
// Amount by which a stock's forecast changes during each price movement // Amount by which a stock's forecast changes during each price movement
export const forecastChangePerPriceMovement = 0.006; export const forecastChangePerPriceMovement = 0.006;
@ -25,9 +25,9 @@ export function getBuyTransactionCost(stock: Stock, shares: number, posType: Pos
// If the number of shares doesn't trigger a price movement, its a simple calculation // If the number of shares doesn't trigger a price movement, its a simple calculation
if (isLong) { if (isLong) {
return shares * stock.getAskPrice() + CONSTANTS.StockMarketCommission; return shares * stock.getAskPrice() + StockMarketConstants.StockMarketCommission;
} else { } else {
return shares * stock.getBidPrice() + CONSTANTS.StockMarketCommission; return shares * stock.getBidPrice() + StockMarketConstants.StockMarketCommission;
} }
} }
@ -50,11 +50,11 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
const isLong = posType === PositionType.Long; const isLong = posType === PositionType.Long;
if (isLong) { if (isLong) {
return shares * stock.getBidPrice() - CONSTANTS.StockMarketCommission; return shares * stock.getBidPrice() - StockMarketConstants.StockMarketCommission;
} else { } else {
// Calculating gains for a short position requires calculating the profit made // Calculating gains for a short position requires calculating the profit made
const origCost = shares * stock.playerAvgShortPx; const origCost = shares * stock.playerAvgShortPx;
const profit = (stock.playerAvgShortPx - stock.getAskPrice()) * shares - CONSTANTS.StockMarketCommission; const profit = (stock.playerAvgShortPx - stock.getAskPrice()) * shares - StockMarketConstants.StockMarketCommission;
return origCost + profit; return origCost + profit;
} }
@ -124,7 +124,7 @@ export function calculateBuyMaxAmount(stock: Stock, posType: PositionType, money
const isLong = posType === PositionType.Long; const isLong = posType === PositionType.Long;
const remainingMoney = money - CONSTANTS.StockMarketCommission; const remainingMoney = money - StockMarketConstants.StockMarketCommission;
const currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice(); const currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();
return Math.floor(remainingMoney / currPrice); return Math.floor(remainingMoney / currPrice);

@ -0,0 +1,15 @@
export const StockMarketConstants = {
//stock tick times in milliseconds
msPerStockUpdate: 6e3,
msPerStockUpdateMin: 4e3,
//defines the length of the flip timer in stock cycles
TicksPerCycle: 75,
// Stockmarket costs Constants
WSEAccountCost: 200e6,
TIXAPICost: 5e9,
MarketData4SCost: 1e9,
MarketDataTixApi4SCost: 25e9,
StockMarketCommission: 100e3,
};

@ -7,7 +7,7 @@ import React, { useState } from "react";
import { getStockMarket4SDataCost, getStockMarket4STixApiCost } from "../StockMarketCosts"; import { getStockMarket4SDataCost, getStockMarket4STixApiCost } from "../StockMarketCosts";
import { CONSTANTS } from "../../Constants"; import { StockMarketConstants } from "../data/Constants";
import { Player } from "@player"; import { Player } from "@player";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { initStockMarket } from "../StockMarket"; import { initStockMarket } from "../StockMarket";
@ -83,16 +83,16 @@ function PurchaseWseAccountButton(props: IProps): React.ReactElement {
if (Player.hasWseAccount) { if (Player.hasWseAccount) {
return; return;
} }
if (!Player.canAfford(CONSTANTS.WSEAccountCost)) { if (!Player.canAfford(StockMarketConstants.WSEAccountCost)) {
return; return;
} }
Player.hasWseAccount = true; Player.hasWseAccount = true;
initStockMarket(); initStockMarket();
Player.loseMoney(CONSTANTS.WSEAccountCost, "stock"); Player.loseMoney(StockMarketConstants.WSEAccountCost, "stock");
props.rerender(); props.rerender();
} }
const cost = CONSTANTS.WSEAccountCost; const cost = StockMarketConstants.WSEAccountCost;
return ( return (
<> <>
<Typography>To begin trading, you must first purchase an account:</Typography> <Typography>To begin trading, you must first purchase an account:</Typography>
@ -109,11 +109,11 @@ function PurchaseTixApiAccessButton(props: IProps): React.ReactElement {
if (Player.hasTixApiAccess) { if (Player.hasTixApiAccess) {
return; return;
} }
if (!Player.canAfford(CONSTANTS.TIXAPICost)) { if (!Player.canAfford(StockMarketConstants.TIXAPICost)) {
return; return;
} }
Player.hasTixApiAccess = true; Player.hasTixApiAccess = true;
Player.loseMoney(CONSTANTS.TIXAPICost, "stock"); Player.loseMoney(StockMarketConstants.TIXAPICost, "stock");
props.rerender(); props.rerender();
} }
@ -124,7 +124,7 @@ function PurchaseTixApiAccessButton(props: IProps): React.ReactElement {
</Typography> </Typography>
); );
} else { } else {
const cost = CONSTANTS.TIXAPICost; const cost = StockMarketConstants.TIXAPICost;
return ( return (
<Button disabled={!Player.canAfford(cost) || !Player.hasWseAccount} onClick={purchaseTixApiAccess}> <Button disabled={!Player.canAfford(cost) || !Player.hasWseAccount} onClick={purchaseTixApiAccess}>
Buy Trade Information eXchange (TIX) API Access -&nbsp; Buy Trade Information eXchange (TIX) API Access -&nbsp;
@ -203,7 +203,7 @@ export function InfoAndPurchases(props: IProps): React.ReactElement {
<Purchase4SMarketDataButton {...props} /> <Purchase4SMarketDataButton {...props} />
<Typography> <Typography>
Commission Fees: Every transaction you make has a{" "} Commission Fees: Every transaction you make has a{" "}
<Money money={CONSTANTS.StockMarketCommission} forPurchase={true} /> commission fee. <Money money={StockMarketConstants.StockMarketCommission} forPurchase={true} /> commission fee.
</Typography> </Typography>
<br /> <br />
<Typography> <Typography>

@ -1,4 +1,4 @@
import { CONSTANTS } from "../../src/Constants"; import { StockMarketConstants } from "../../src/StockMarket/data/Constants";
import { Player } from "../../src/Player"; import { Player } from "../../src/Player";
import { Company } from "../../src/Company/Company"; import { Company } from "../../src/Company/Company";
@ -42,7 +42,7 @@ jest.mock(`!!raw-loader!../NetscriptDefinitions.d.ts`, () => "", {
// })); // }));
describe("Stock Market Tests", function () { describe("Stock Market Tests", function () {
const commission = CONSTANTS.StockMarketCommission; const commission = StockMarketConstants.StockMarketCommission;
// Generic Stock object that can be used by each test // Generic Stock object that can be used by each test
let stock: Stock; let stock: Stock;