Skip to content

Commit

Permalink
Update Pnl
Browse files Browse the repository at this point in the history
  • Loading branch information
prevostc committed Apr 22, 2024
1 parent 324761a commit 8f0d542
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 32 deletions.
11 changes: 6 additions & 5 deletions src/utils/pnl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ZERO_BD, bigDecMin } from "./decimal"

class PnLStateEntry {
constructor(
public boughtShares: BigDecimal,
public remainingShares: BigDecimal,
public entryPrice: BigDecimal,
) {}
Expand All @@ -20,7 +19,6 @@ export class PnLState {
res.push(this.realizedPnl)
for (let idx = 0; idx < this.sharesFifo.length; idx++) {
let entry = this.sharesFifo[idx]
res.push(entry.boughtShares)
res.push(entry.remainingShares)
res.push(entry.entryPrice)
}
Expand All @@ -32,10 +30,9 @@ export class PnLState {
let realizedPnl = data.shift() as BigDecimal
let sharesFifo = new Array<PnLStateEntry>()
while (data.length > 0) {
let boughtShares = data.shift() as BigDecimal
let remainingShares = data.shift() as BigDecimal
let entryPrice = data.shift() as BigDecimal
sharesFifo.push(new PnLStateEntry(boughtShares, remainingShares, entryPrice))
sharesFifo.push(new PnLStateEntry(remainingShares, entryPrice))
}

return new PnLState(realizedPnl, sharesFifo)
Expand All @@ -58,8 +55,9 @@ export class PnLCalc {
return
}

// bought shares
if (trxShares.gt(ZERO_BD)) {
this.state.sharesFifo.push(new PnLStateEntry(trxShares, trxShares, trxPrice))
this.state.sharesFifo.push(new PnLStateEntry(trxShares, trxPrice))
return
}

Expand All @@ -83,6 +81,9 @@ export class PnLCalc {
}

this.state.realizedPnl = this.state.realizedPnl.plus(trxPnl)

// evict empty entries
this.state.sharesFifo = this.state.sharesFifo.filter((entry) => !entry.remainingShares.equals(ZERO_BD))
return
}

Expand Down
37 changes: 10 additions & 27 deletions tests/utils/pnl.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,42 @@ describe("PnLState", () => {

test("Can serialize and deserialize pnl state with one entry", () => {
const realizedPnl = BigDecimal.fromString("100")
const boughtShares = BigDecimal.fromString("10")
const remainingShares = BigDecimal.fromString("5")
const entryPrice = BigDecimal.fromString("20")
const state = PnLState.deserialize([realizedPnl, boughtShares, remainingShares, entryPrice])
const state = PnLState.deserialize([realizedPnl, remainingShares, entryPrice])
assert.assertTrue(state.realizedPnl.equals(realizedPnl))
assert.assertTrue(state.sharesFifo.length === 1)
assert.assertTrue(state.sharesFifo[0].boughtShares.equals(boughtShares))
assert.assertTrue(state.sharesFifo[0].remainingShares.equals(remainingShares))
assert.assertTrue(state.sharesFifo[0].entryPrice.equals(entryPrice))

const serialized = state.serialize()
assert.assertTrue(serialized.length === 4)
assert.assertTrue(serialized.length === 3)
assert.assertTrue(serialized[0].equals(realizedPnl))
assert.assertTrue(serialized[1].equals(boughtShares))
assert.assertTrue(serialized[2].equals(remainingShares))
assert.assertTrue(serialized[3].equals(entryPrice))
assert.assertTrue(serialized[1].equals(remainingShares))
assert.assertTrue(serialized[2].equals(entryPrice))
})

test("Can serialize and deserialize pnl state with multiple entries", () => {
const realizedPnl = BigDecimal.fromString("100")
const boughtShares1 = BigDecimal.fromString("10")
const remainingShares1 = BigDecimal.fromString("5")
const entryPrice1 = BigDecimal.fromString("20")
const boughtShares2 = BigDecimal.fromString("20")
const remainingShares2 = BigDecimal.fromString("10")
const entryPrice2 = BigDecimal.fromString("30")
const state = PnLState.deserialize([
realizedPnl,
boughtShares1,
remainingShares1,
entryPrice1,
boughtShares2,
remainingShares2,
entryPrice2,
])
const state = PnLState.deserialize([realizedPnl, remainingShares1, entryPrice1, remainingShares2, entryPrice2])
assert.assertTrue(state.realizedPnl.equals(realizedPnl))
assert.assertTrue(state.sharesFifo.length === 2)
assert.assertTrue(state.sharesFifo[0].boughtShares.equals(boughtShares1))
assert.assertTrue(state.sharesFifo[0].remainingShares.equals(remainingShares1))
assert.assertTrue(state.sharesFifo[0].entryPrice.equals(entryPrice1))
assert.assertTrue(state.sharesFifo[1].boughtShares.equals(boughtShares2))
assert.assertTrue(state.sharesFifo[1].remainingShares.equals(remainingShares2))
assert.assertTrue(state.sharesFifo[1].entryPrice.equals(entryPrice2))

const serialized = state.serialize()
assert.assertTrue(serialized.length === 7)
assert.assertTrue(serialized.length === 5)
assert.assertTrue(serialized[0].equals(realizedPnl))
assert.assertTrue(serialized[1].equals(boughtShares1))
assert.assertTrue(serialized[2].equals(remainingShares1))
assert.assertTrue(serialized[3].equals(entryPrice1))
assert.assertTrue(serialized[4].equals(boughtShares2))
assert.assertTrue(serialized[5].equals(remainingShares2))
assert.assertTrue(serialized[6].equals(entryPrice2))
assert.assertTrue(serialized[1].equals(remainingShares1))
assert.assertTrue(serialized[2].equals(entryPrice1))
assert.assertTrue(serialized[3].equals(remainingShares2))
assert.assertTrue(serialized[4].equals(entryPrice2))
})
})

Expand Down

0 comments on commit 8f0d542

Please sign in to comment.