@shipload/sdk 2.0.0-rc2 → 2.0.0-rc20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -349
- package/lib/shipload.d.ts +1658 -1126
- package/lib/shipload.js +6847 -3082
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +6468 -2793
- package/lib/shipload.m.js.map +1 -1
- package/package.json +6 -4
- package/src/capabilities/crafting.ts +22 -0
- package/src/capabilities/gathering.ts +36 -0
- package/src/capabilities/guards.ts +3 -8
- package/src/capabilities/hauling.ts +22 -0
- package/src/capabilities/index.ts +4 -1
- package/src/capabilities/modules.ts +57 -0
- package/src/capabilities/storage.ts +101 -9
- package/src/contracts/server.ts +717 -293
- package/src/data/capabilities.ts +408 -0
- package/src/data/categories.ts +55 -0
- package/src/data/colors.ts +71 -0
- package/src/data/items.json +17 -0
- package/src/data/locations.ts +53 -0
- package/src/data/nebula-adjectives.json +211 -0
- package/src/data/nebula-nouns.json +151 -0
- package/src/data/recipes.ts +587 -0
- package/src/data/syllables.json +1386 -780
- package/src/data/tiers.ts +45 -0
- package/src/derivation/crafting.ts +287 -0
- package/src/derivation/index.ts +30 -0
- package/src/derivation/location-size.ts +15 -0
- package/src/derivation/resources.ts +136 -0
- package/src/derivation/stats.ts +146 -0
- package/src/derivation/stratum.ts +134 -0
- package/src/derivation/tiers.ts +54 -0
- package/src/entities/cargo-utils.ts +10 -68
- package/src/entities/container.ts +37 -0
- package/src/entities/entity-inventory.ts +13 -13
- package/src/entities/inventory-accessor.ts +2 -6
- package/src/entities/location.ts +5 -200
- package/src/entities/makers.ts +136 -17
- package/src/entities/player.ts +1 -274
- package/src/entities/ship-deploy.ts +258 -0
- package/src/entities/ship.ts +28 -34
- package/src/entities/warehouse.ts +35 -7
- package/src/errors.ts +59 -5
- package/src/format.ts +12 -0
- package/src/index-module.ts +233 -50
- package/src/managers/actions.ts +138 -88
- package/src/managers/context.ts +19 -9
- package/src/managers/index.ts +0 -1
- package/src/managers/locations.ts +2 -85
- package/src/market/items.ts +93 -0
- package/src/nft/description.ts +176 -0
- package/src/nft/deserializers.ts +81 -0
- package/src/nft/index.ts +2 -0
- package/src/resolution/describe-module.ts +165 -0
- package/src/resolution/display-name.ts +39 -0
- package/src/resolution/resolve-item.ts +343 -0
- package/src/scheduling/projection.ts +220 -67
- package/src/scheduling/schedule.ts +2 -2
- package/src/shipload.ts +10 -5
- package/src/subscriptions/connection.ts +154 -0
- package/src/subscriptions/debug.ts +17 -0
- package/src/subscriptions/index.ts +5 -0
- package/src/subscriptions/manager.ts +240 -0
- package/src/subscriptions/mappers.ts +28 -0
- package/src/subscriptions/types.ts +143 -0
- package/src/travel/travel.ts +30 -17
- package/src/types/capabilities.ts +11 -14
- package/src/types/entity-traits.ts +3 -4
- package/src/types/entity.ts +9 -6
- package/src/types.ts +61 -55
- package/src/utils/system.ts +66 -53
- package/src/capabilities/extraction.ts +0 -37
- package/src/data/goods.json +0 -23
- package/src/managers/trades.ts +0 -119
- package/src/market/goods.ts +0 -31
- package/src/market/market.ts +0 -208
- package/src/market/rolls.ts +0 -8
- package/src/trading/collect.ts +0 -938
- package/src/trading/deal.ts +0 -207
- package/src/trading/trade.ts +0 -203
package/src/trading/deal.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import {Int64, UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
|
|
2
|
-
import {Coordinates, GoodPrice, PRECISION, ShipLike} from '../types'
|
|
3
|
-
import {Location} from '../entities/location'
|
|
4
|
-
import {Ship} from '../entities/ship'
|
|
5
|
-
import {
|
|
6
|
-
distanceBetweenCoordinates,
|
|
7
|
-
type EstimatedTravelTime,
|
|
8
|
-
estimateTravelTime,
|
|
9
|
-
} from '../travel/travel'
|
|
10
|
-
import {calculateProfitPerSecond, calculateTradeProfit, isProfitable} from './trade'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Trading deal interface representing a profitable trade opportunity
|
|
14
|
-
*/
|
|
15
|
-
export interface Deal {
|
|
16
|
-
/** Origin location */
|
|
17
|
-
origin: Location
|
|
18
|
-
/** Destination location */
|
|
19
|
-
destination: Location
|
|
20
|
-
/** Good to trade */
|
|
21
|
-
good: GoodPrice
|
|
22
|
-
/** Distance between origin and destination */
|
|
23
|
-
distance: UInt64
|
|
24
|
-
/** Available supply at origin */
|
|
25
|
-
supply: UInt16
|
|
26
|
-
/** Buy price at origin */
|
|
27
|
-
buyPrice: UInt32
|
|
28
|
-
/** Sell price at destination */
|
|
29
|
-
sellPrice: UInt32
|
|
30
|
-
/** Profit per unit */
|
|
31
|
-
profitPerUnit: UInt32
|
|
32
|
-
/** Maximum quantity that can be traded */
|
|
33
|
-
maxQuantity: UInt32
|
|
34
|
-
/** Total profit for max quantity */
|
|
35
|
-
totalProfit: Int64
|
|
36
|
-
/** Estimated travel time in seconds */
|
|
37
|
-
travelTime: UInt32
|
|
38
|
-
/** Detailed breakdown of travel time components */
|
|
39
|
-
travelTimeBreakdown: EstimatedTravelTime
|
|
40
|
-
/** Profit per second (floating point for UI display) */
|
|
41
|
-
profitPerSecond: number
|
|
42
|
-
/** Profit margin percentage (floating point for UI display) */
|
|
43
|
-
marginPercent: number
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Options for finding deals
|
|
48
|
-
*/
|
|
49
|
-
export interface FindDealsOptions {
|
|
50
|
-
/** Maximum number of deals to return */
|
|
51
|
-
maxDeals?: number
|
|
52
|
-
/** Maximum search distance */
|
|
53
|
-
maxDistance?: number
|
|
54
|
-
/** Player's current balance (for affordability filtering) */
|
|
55
|
-
playerBalance?: UInt64Type
|
|
56
|
-
/** Minimum profit per second threshold */
|
|
57
|
-
minProfitPerSecond?: number
|
|
58
|
-
/** Minimum profit margin percentage */
|
|
59
|
-
minMarginPercent?: number
|
|
60
|
-
/** Override available cargo space (in mass units). If provided, uses this instead of calculating from ship's current cargo. */
|
|
61
|
-
availableSpace?: number
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Calculate deals for a ship from a specific origin location
|
|
66
|
-
*/
|
|
67
|
-
export async function findDealsForShip(
|
|
68
|
-
ship: Ship,
|
|
69
|
-
originLocation: Coordinates,
|
|
70
|
-
getNearbyLocations: (origin: Coordinates, maxDistance: number) => Promise<Location[]>,
|
|
71
|
-
getMarketPrices: (location: Coordinates) => Promise<GoodPrice[]>,
|
|
72
|
-
options: FindDealsOptions = {}
|
|
73
|
-
): Promise<Deal[]> {
|
|
74
|
-
const {
|
|
75
|
-
maxDeals = 10,
|
|
76
|
-
maxDistance = 20 * PRECISION,
|
|
77
|
-
playerBalance,
|
|
78
|
-
minProfitPerSecond = 0,
|
|
79
|
-
minMarginPercent = 0,
|
|
80
|
-
availableSpace,
|
|
81
|
-
} = options
|
|
82
|
-
|
|
83
|
-
const balance = playerBalance !== undefined ? UInt64.from(playerBalance) : undefined
|
|
84
|
-
|
|
85
|
-
const origin = Location.from(originLocation)
|
|
86
|
-
const originPrices = await getMarketPrices(originLocation)
|
|
87
|
-
origin.setMarketPrices(originPrices)
|
|
88
|
-
|
|
89
|
-
// Get nearby locations
|
|
90
|
-
const nearbyLocations = await getNearbyLocations(originLocation, maxDistance)
|
|
91
|
-
|
|
92
|
-
const deals: Deal[] = []
|
|
93
|
-
const currentMass = ship.totalMass
|
|
94
|
-
const shipCapacity = ship.maxCapacity
|
|
95
|
-
const effectiveAvailableMass =
|
|
96
|
-
availableSpace !== undefined
|
|
97
|
-
? UInt64.from(availableSpace)
|
|
98
|
-
: currentMass.lt(shipCapacity)
|
|
99
|
-
? shipCapacity.subtracting(currentMass)
|
|
100
|
-
: UInt64.zero
|
|
101
|
-
|
|
102
|
-
// Check each nearby location
|
|
103
|
-
for (const destLocation of nearbyLocations) {
|
|
104
|
-
const destinationPrices = await getMarketPrices(destLocation.coordinates)
|
|
105
|
-
destLocation.setMarketPrices(destinationPrices)
|
|
106
|
-
|
|
107
|
-
const distance = distanceBetweenCoordinates(originLocation, destLocation.coordinates)
|
|
108
|
-
|
|
109
|
-
// Compare prices for each good
|
|
110
|
-
for (const originGood of originPrices) {
|
|
111
|
-
const destGood = destinationPrices.find((g) => g.id.equals(originGood.id))
|
|
112
|
-
if (!destGood) continue
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
!isProfitable(originGood.price, destGood.price) ||
|
|
116
|
-
originGood.supply.equals(UInt16.from(0))
|
|
117
|
-
) {
|
|
118
|
-
continue
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Calculate max quantity based on balance, cargo space, and supply
|
|
122
|
-
const canAfford =
|
|
123
|
-
balance !== undefined
|
|
124
|
-
? balance.dividing(originGood.price)
|
|
125
|
-
: UInt64.from(Number.MAX_SAFE_INTEGER)
|
|
126
|
-
const canHaul = effectiveAvailableMass.dividing(originGood.good.mass)
|
|
127
|
-
const supplyLimit = UInt64.from(originGood.supply)
|
|
128
|
-
|
|
129
|
-
// Find minimum of canAfford, canHaul, supplyLimit
|
|
130
|
-
let maxQuantity = canAfford
|
|
131
|
-
if (canHaul.lt(maxQuantity)) maxQuantity = canHaul
|
|
132
|
-
if (supplyLimit.lt(maxQuantity)) maxQuantity = supplyLimit
|
|
133
|
-
|
|
134
|
-
if (maxQuantity.equals(UInt64.zero)) continue
|
|
135
|
-
|
|
136
|
-
// Calculate travel time with cargo (includes recharge + load time)
|
|
137
|
-
const cargoMass = originGood.good.mass.multiplying(maxQuantity)
|
|
138
|
-
const availableSpaceUInt = UInt64.from(availableSpace)
|
|
139
|
-
const baseMass =
|
|
140
|
-
availableSpace !== undefined
|
|
141
|
-
? shipCapacity.gte(availableSpaceUInt)
|
|
142
|
-
? shipCapacity.subtracting(availableSpaceUInt)
|
|
143
|
-
: UInt64.zero
|
|
144
|
-
: currentMass
|
|
145
|
-
const totalMass = baseMass.adding(cargoMass)
|
|
146
|
-
const needsRecharge = !ship.hasEnergyFor(distance)
|
|
147
|
-
const travelEstimate = estimateTravelTime(ship as ShipLike, totalMass, distance, {
|
|
148
|
-
needsRecharge,
|
|
149
|
-
loadMass: Number(cargoMass),
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
// Calculate profitability metrics using trade.ts functions
|
|
153
|
-
const tradeCalc = calculateTradeProfit(maxQuantity, originGood.price, destGood.price)
|
|
154
|
-
const profitPerUnit = destGood.price.subtracting(originGood.price)
|
|
155
|
-
const profitPerSecond = calculateProfitPerSecond(tradeCalc.profit, travelEstimate.total)
|
|
156
|
-
|
|
157
|
-
// Apply filters
|
|
158
|
-
if (profitPerSecond < minProfitPerSecond) continue
|
|
159
|
-
if (tradeCalc.margin < minMarginPercent) continue
|
|
160
|
-
|
|
161
|
-
deals.push({
|
|
162
|
-
origin,
|
|
163
|
-
destination: destLocation,
|
|
164
|
-
good: originGood,
|
|
165
|
-
distance,
|
|
166
|
-
supply: originGood.supply,
|
|
167
|
-
buyPrice: originGood.price,
|
|
168
|
-
sellPrice: destGood.price,
|
|
169
|
-
profitPerUnit,
|
|
170
|
-
maxQuantity: UInt32.from(maxQuantity),
|
|
171
|
-
totalProfit: tradeCalc.profit,
|
|
172
|
-
travelTime: travelEstimate.total,
|
|
173
|
-
travelTimeBreakdown: travelEstimate,
|
|
174
|
-
profitPerSecond,
|
|
175
|
-
marginPercent: tradeCalc.margin,
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Sort by profit per second (descending)
|
|
181
|
-
deals.sort((a, b) => b.profitPerSecond - a.profitPerSecond)
|
|
182
|
-
|
|
183
|
-
return deals.slice(0, maxDeals)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Find the single best deal for a ship from a specific origin location
|
|
188
|
-
*/
|
|
189
|
-
export async function findBestDeal(
|
|
190
|
-
ship: Ship,
|
|
191
|
-
originLocation: Coordinates,
|
|
192
|
-
getNearbyLocations: (origin: Coordinates, maxDistance: number) => Promise<Location[]>,
|
|
193
|
-
getMarketPrices: (location: Coordinates) => Promise<GoodPrice[]>,
|
|
194
|
-
options: FindDealsOptions = {}
|
|
195
|
-
): Promise<Deal | undefined> {
|
|
196
|
-
const deals = await findDealsForShip(
|
|
197
|
-
ship,
|
|
198
|
-
originLocation,
|
|
199
|
-
getNearbyLocations,
|
|
200
|
-
getMarketPrices,
|
|
201
|
-
{
|
|
202
|
-
...options,
|
|
203
|
-
maxDeals: 1,
|
|
204
|
-
}
|
|
205
|
-
)
|
|
206
|
-
return deals[0]
|
|
207
|
-
}
|
package/src/trading/trade.ts
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import {Int64, Int64Type, UInt32, UInt32Type, UInt64} from '@wharfkit/antelope'
|
|
2
|
-
import {Ship} from '../entities/ship'
|
|
3
|
-
import {Player} from '../entities/player'
|
|
4
|
-
import {GoodPrice} from '../types'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Trade calculation result
|
|
8
|
-
*/
|
|
9
|
-
export interface TradeCalculation {
|
|
10
|
-
maxQuantity: number
|
|
11
|
-
totalCost: number
|
|
12
|
-
totalMass: UInt64
|
|
13
|
-
affordableQuantity: number
|
|
14
|
-
spaceForQuantity: number
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Calculate updated weighted average cargo cost after purchase.
|
|
19
|
-
* Matches contract logic: (paid * owned + cost) / (owned + quantity)
|
|
20
|
-
*
|
|
21
|
-
* @param currentPaid - Current average cost per unit (from cargo.paid)
|
|
22
|
-
* @param currentOwned - Current owned quantity
|
|
23
|
-
* @param purchaseCost - Total cost of new purchase (price * quantity)
|
|
24
|
-
* @param purchaseQuantity - Quantity being purchased
|
|
25
|
-
* @returns New weighted average cost per unit
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* // Owned 10 units at 100 each, buying 5 more at 120 each
|
|
29
|
-
* const newPaid = calculateUpdatedCargoCost(
|
|
30
|
-
* UInt64.from(100),
|
|
31
|
-
* UInt32.from(10),
|
|
32
|
-
* UInt64.from(600),
|
|
33
|
-
* UInt32.from(5)
|
|
34
|
-
* )
|
|
35
|
-
* // Result: (100*10 + 600) / (10+5) = 106.67 per unit
|
|
36
|
-
*/
|
|
37
|
-
export function calculateUpdatedCargoCost(
|
|
38
|
-
currentPaid: UInt64,
|
|
39
|
-
currentOwned: UInt32,
|
|
40
|
-
purchaseCost: UInt64,
|
|
41
|
-
purchaseQuantity: UInt32
|
|
42
|
-
): UInt64 {
|
|
43
|
-
// Match contract: (paid * owned + cost) / (owned + quantity)
|
|
44
|
-
const numerator = currentPaid.multiplying(currentOwned).adding(purchaseCost)
|
|
45
|
-
const denominator = UInt32.from(currentOwned).adding(purchaseQuantity)
|
|
46
|
-
return numerator.dividing(denominator)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Calculate the maximum quantity of a good a ship can buy
|
|
51
|
-
* considering both space and player balance
|
|
52
|
-
*/
|
|
53
|
-
export function calculateMaxTradeQuantity(
|
|
54
|
-
ship: Ship,
|
|
55
|
-
player: Player,
|
|
56
|
-
goodPrice: GoodPrice
|
|
57
|
-
): TradeCalculation {
|
|
58
|
-
const pricePerUnit = UInt32.from(goodPrice.price)
|
|
59
|
-
const massPerUnit = UInt32.from(goodPrice.good.mass)
|
|
60
|
-
|
|
61
|
-
const spaceForQuantity = ship.availableCapacity.dividing(massPerUnit)
|
|
62
|
-
const affordableQuantity = player.balance.dividing(pricePerUnit)
|
|
63
|
-
const maxQuantity = spaceForQuantity.lt(affordableQuantity)
|
|
64
|
-
? spaceForQuantity
|
|
65
|
-
: affordableQuantity
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
maxQuantity: Number(maxQuantity),
|
|
69
|
-
totalCost: Number(maxQuantity.multiplying(pricePerUnit)),
|
|
70
|
-
totalMass: UInt64.from(maxQuantity.multiplying(massPerUnit)),
|
|
71
|
-
affordableQuantity: Number(affordableQuantity),
|
|
72
|
-
spaceForQuantity: Number(spaceForQuantity),
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Trade profit calculation result
|
|
78
|
-
*/
|
|
79
|
-
export interface TradeProfitResult {
|
|
80
|
-
revenue: UInt64
|
|
81
|
-
cost: UInt64
|
|
82
|
-
profit: Int64
|
|
83
|
-
margin: number
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Calculate profit for a trade route
|
|
88
|
-
*/
|
|
89
|
-
export function calculateTradeProfit(
|
|
90
|
-
quantity: UInt32Type,
|
|
91
|
-
buyPrice: UInt32Type,
|
|
92
|
-
sellPrice: UInt32Type
|
|
93
|
-
): TradeProfitResult {
|
|
94
|
-
const qty = UInt32.from(quantity)
|
|
95
|
-
const buy = UInt32.from(buyPrice)
|
|
96
|
-
const sell = UInt32.from(sellPrice)
|
|
97
|
-
|
|
98
|
-
const cost = UInt64.from(qty).multiplying(buy)
|
|
99
|
-
const revenue = UInt64.from(qty).multiplying(sell)
|
|
100
|
-
const profit = Int64.from(revenue).subtracting(cost)
|
|
101
|
-
const margin = cost.gt(UInt64.zero) ? (Number(profit) / Number(cost)) * 100 : 0
|
|
102
|
-
|
|
103
|
-
return {revenue, cost, profit, margin}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Calculate profit per unit of mass
|
|
108
|
-
*/
|
|
109
|
-
export function calculateProfitPerMass(
|
|
110
|
-
quantity: number,
|
|
111
|
-
buyPrice: number,
|
|
112
|
-
sellPrice: number,
|
|
113
|
-
massPerUnit: number
|
|
114
|
-
): number {
|
|
115
|
-
const profit = (sellPrice - buyPrice) * quantity
|
|
116
|
-
const totalMass = quantity * massPerUnit
|
|
117
|
-
return totalMass > 0 ? profit / totalMass : 0
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Calculate profit per second for a trade route
|
|
122
|
-
*/
|
|
123
|
-
export function calculateProfitPerSecond(profit: Int64Type, travelTimeSeconds: UInt32Type): number {
|
|
124
|
-
const t = UInt32.from(travelTimeSeconds)
|
|
125
|
-
return t.gt(UInt32.zero) ? Number(profit) / Number(t) : 0
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Find the best good to trade between two locations
|
|
130
|
-
*/
|
|
131
|
-
export function findBestGoodToTrade(
|
|
132
|
-
ship: Ship,
|
|
133
|
-
player: Player,
|
|
134
|
-
originPrices: GoodPrice[],
|
|
135
|
-
destPrices: GoodPrice[],
|
|
136
|
-
travelTimeSeconds: UInt32Type
|
|
137
|
-
): {
|
|
138
|
-
good: GoodPrice
|
|
139
|
-
quantity: number
|
|
140
|
-
profit: number
|
|
141
|
-
profitPerSecond: number
|
|
142
|
-
margin: number
|
|
143
|
-
} | null {
|
|
144
|
-
let bestTrade: {
|
|
145
|
-
good: GoodPrice
|
|
146
|
-
quantity: number
|
|
147
|
-
profit: number
|
|
148
|
-
profitPerSecond: number
|
|
149
|
-
margin: number
|
|
150
|
-
} | null = null
|
|
151
|
-
let bestProfitPerSecond = 0
|
|
152
|
-
|
|
153
|
-
for (const originPrice of originPrices) {
|
|
154
|
-
const destPrice = destPrices.find((p) => p.id.equals(originPrice.id))
|
|
155
|
-
if (!destPrice) continue
|
|
156
|
-
|
|
157
|
-
if (!isProfitable(originPrice.price, destPrice.price)) continue
|
|
158
|
-
|
|
159
|
-
const calc = calculateMaxTradeQuantity(ship, player, originPrice)
|
|
160
|
-
if (calc.maxQuantity === 0) continue
|
|
161
|
-
|
|
162
|
-
const tradeResult = calculateTradeProfit(
|
|
163
|
-
calc.maxQuantity,
|
|
164
|
-
originPrice.price,
|
|
165
|
-
destPrice.price
|
|
166
|
-
)
|
|
167
|
-
const profitPerSecond = calculateProfitPerSecond(tradeResult.profit, travelTimeSeconds)
|
|
168
|
-
|
|
169
|
-
if (profitPerSecond > bestProfitPerSecond) {
|
|
170
|
-
bestProfitPerSecond = profitPerSecond
|
|
171
|
-
bestTrade = {
|
|
172
|
-
good: originPrice,
|
|
173
|
-
quantity: calc.maxQuantity,
|
|
174
|
-
profit: Number(tradeResult.profit),
|
|
175
|
-
profitPerSecond,
|
|
176
|
-
margin: tradeResult.margin,
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return bestTrade
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Calculate break-even price for selling cargo
|
|
186
|
-
*/
|
|
187
|
-
export function calculateBreakEvenPrice(costPaid: number, quantity: number): number {
|
|
188
|
-
return quantity > 0 ? costPaid / quantity : 0
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Check if a trade is profitable
|
|
193
|
-
*/
|
|
194
|
-
export function isProfitable(buyPrice: UInt32Type, sellPrice: UInt32Type): boolean {
|
|
195
|
-
return UInt32.from(sellPrice).gt(UInt32.from(buyPrice))
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Calculate return on investment percentage
|
|
200
|
-
*/
|
|
201
|
-
export function calculateROI(cost: number, profit: number): number {
|
|
202
|
-
return cost > 0 ? (profit / cost) * 100 : 0
|
|
203
|
-
}
|