mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 20:55:44 +01:00
STOCKMARKET: Move and Reorganize Constants (#688)
This commit is contained in:
parent
e9bbe57902
commit
a85efbc4da
@ -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);
|
||||||
|
15
src/StockMarket/data/Constants.ts
Normal file
15
src/StockMarket/data/Constants.ts
Normal file
@ -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 -
|
Buy Trade Information eXchange (TIX) API Access -
|
||||||
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user