From bd02ec4e6a3de793737bba5233430abbe2f2f194 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 27 Jun 2024 12:02:40 +0300 Subject: [PATCH 1/5] Add mock trades --- .../helpers/__test__/helpers/index.js | 11 ++ .../helpers/__test__/helpers/mock-trades.js | 113 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/mock-trades.js diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js new file mode 100644 index 00000000..a195cc77 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js @@ -0,0 +1,11 @@ +'use strict' + +const { + mockTradesForNextYear, + mockTrades +} = require('./mock-trades') + +module.exports = { + mockTradesForNextYear, + mockTrades +} diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/mock-trades.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/mock-trades.js new file mode 100644 index 00000000..203829c7 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/mock-trades.js @@ -0,0 +1,113 @@ +'use strict' + +const mockTradesForNextYear = [ + { + symbol: 'tUSTUSD', + mtsCreate: Date.UTC(2024, 3, 27), + execAmount: -200, + execPrice: 0.98 + }, + { + isAdditionalTrxMovements: true, + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2024, 3, 1), + execAmount: -1, + execPrice: 41_000 + }, + { + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2024, 2, 17), + execAmount: -5, + execPrice: 61_000 + }, + { + isAdditionalTrxMovements: true, + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2024, 1, 8), + execAmount: -3, + execPrice: 44_000 + }, + { + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2024, 0, 14), + execAmount: 2, + execPrice: 48_000 + } +] +const mockTrades = [ + { + symbol: 'tUSTEUR', + mtsCreate: Date.UTC(2023, 6, 21), + execAmount: -100, + execPrice: 0.9, + firstSymbPriceUsd: 1.05, + lastSymbPriceUsd: 0.95 + }, + { + symbol: 'tETHUST', + mtsCreate: Date.UTC(2023, 5, 11), + execAmount: -1, + execPrice: 2800, + firstSymbPriceUsd: 3_110, + lastSymbPriceUsd: 1.11 + }, + { + symbol: 'tETHBTC', + mtsCreate: Date.UTC(2023, 4, 22), + execAmount: -1, + execPrice: 0.055, + firstSymbPriceUsd: 2_650, + lastSymbPriceUsd: 48_000 + }, + { + symbol: 'tETHUSD', + mtsCreate: Date.UTC(2023, 4, 10), + execAmount: -1, + execPrice: 2_000 + }, + { + symbol: 'tETHUSD', + mtsCreate: Date.UTC(2023, 3, 10), + execAmount: -2, + execPrice: 3_200 + }, + { + isAdditionalTrxMovements: true, + symbol: 'tETHUSD', + mtsCreate: Date.UTC(2023, 3, 2), + execAmount: -2, + execPrice: 3000 + }, + { + symbol: 'tETHBTC', + mtsCreate: Date.UTC(2023, 2, 23), + execAmount: 10, + execPrice: 0.05, + firstSymbPriceUsd: 2_601, + lastSymbPriceUsd: 50_000 + }, + { + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2023, 2, 3), + execAmount: -2, + execPrice: 33_000 + }, + { + isAdditionalTrxMovements: true, + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2023, 1, 5), + execAmount: 20, + execPrice: 43_000 + }, + { + symbol: 'tBTCUSD', + mtsCreate: Date.UTC(2023, 0, 10), + execAmount: 3, + execPrice: 20_000 + } +] + +module.exports = { + mockTradesForNextYear, + mockTrades +} From 4e97f45736a6c5aacd2e18ebd6b67716aabb49e7 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 27 Jun 2024 12:05:16 +0300 Subject: [PATCH 2/5] Add helper to get mocked trades --- .../__test__/helpers/get-mocked-trades.js | 56 +++++++++++++++++++ .../helpers/__test__/helpers/index.js | 4 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/get-mocked-trades.js diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/get-mocked-trades.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/get-mocked-trades.js new file mode 100644 index 00000000..a657fa13 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/get-mocked-trades.js @@ -0,0 +1,56 @@ +'use strict' + +const splitSymbolPairs = require( + 'bfx-report/workers/loc.api/helpers/split-symbol-pairs' +) + +module.exports = (mockTrades, opts) => { + const missingFields = { + _id: 1, + id: 1, + orderID: 1, + orderType: 'EXCHANGE LIMIT', + orderPrice: null, + maker: 1, + fee: -0.5, + feeCurrency: 'USD', + subUserId: null, + user_id: 1, + + firstSymb: null, + lastSymb: null, + firstSymbPriceUsd: null, + lastSymbPriceUsd: null + } + + return mockTrades.map((trade, i) => { + const isAdditionalTrxMovements = opts?.isAdditionalTrxMovements ?? + trade?.isAdditionalTrxMovements ?? + trade?.isMovements ?? + trade?.isLedgers + const [firstSymb, lastSymb] = splitSymbolPairs(trade.symbol) + + return { + ...missingFields, + + isAdditionalTrxMovements, + isMovements: !!trade?.isMovements, + isLedgers: !!trade?.isLedgers, + isTrades: !isAdditionalTrxMovements, + _id: i + 1, + id: i + 1, + orderID: i + 1, + orderPrice: trade.execPrice, + firstSymb, + lastSymb, + firstSymbPriceUsd: lastSymb === 'USD' ? trade.execPrice : null, + lastSymbPriceUsd: lastSymb === 'USD' ? 1 : null, + + ...trade, + + mtsCreate: opts?.year + ? new Date(trade.mtsCreate).setUTCFullYear(opts?.year) + : trade.mtsCreate + } + }) +} diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js index a195cc77..2013b36b 100644 --- a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/helpers/index.js @@ -4,8 +4,10 @@ const { mockTradesForNextYear, mockTrades } = require('./mock-trades') +const getMockedTrades = require('./get-mocked-trades') module.exports = { mockTradesForNextYear, - mockTrades + mockTrades, + getMockedTrades } From 24d1cf6ee89d4e556ba33a1db8cda2c81aa3a515 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 27 Jun 2024 12:10:01 +0300 Subject: [PATCH 3/5] Add test case to test buy trades with unrealized profit --- .../helpers/__test__/test-cases/index.js | 9 ++++ .../test-buy-trades-with-unrealized-profit.js | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-buy-trades-with-unrealized-profit.js diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js new file mode 100644 index 00000000..c6143058 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js @@ -0,0 +1,9 @@ +'use strict' + +const testBuyTradesWithUnrealizedProfit = require( + './test-buy-trades-with-unrealized-profit' +) + +module.exports = { + testBuyTradesWithUnrealizedProfit +} diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-buy-trades-with-unrealized-profit.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-buy-trades-with-unrealized-profit.js new file mode 100644 index 00000000..bfc776e3 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-buy-trades-with-unrealized-profit.js @@ -0,0 +1,49 @@ +'use strict' + +const { assert } = require('chai') +const BigNumber = require('bignumber.js') + +module.exports = (arr, index, props) => { + const trade = arr[index] + const { + isAdditionalTrxMovements, + mtsCreate, + firstSymb, + lastSymb, + execAmount, + execPrice, + + buyFilledAmount + } = props ?? {} + + assert.isObject(trade) + assert.isBoolean(trade.isBuyTradesWithUnrealizedProfitForPrevPeriod) + assert.isOk(trade.isBuyTradesWithUnrealizedProfitForPrevPeriod) + assert.isBoolean(trade.isBuyTrx) + assert.isOk(trade.isBuyTrx) + assert.isBoolean(trade.isBuyTrxHistFilled) + assert.isNotOk(trade.isBuyTrxHistFilled) + assert.instanceOf(trade.proceedsForBuyTrxUsd, BigNumber) + assert.equal(trade.proceedsForBuyTrxUsd.toNumber(), 0) + assert.instanceOf(trade.proceedsForBuyTrxUsd, BigNumber) + assert.equal(trade.proceedsForBuyTrxUsd.toNumber(), 0) + assert.isNumber(trade.firstSymbPriceUsd) + assert.isNumber(trade.lastSymbPriceUsd) + assert.isArray(trade.saleTrxsForRealizedProfit) + + assert.isBoolean(trade.isAdditionalTrxMovements) + assert.equal(trade.isAdditionalTrxMovements, isAdditionalTrxMovements) + assert.isNumber(trade.mtsCreate) + assert.equal(trade.mtsCreate, mtsCreate) + assert.isString(trade.firstSymb) + assert.equal(trade.firstSymb, firstSymb) + assert.isString(trade.lastSymb) + assert.equal(trade.lastSymb, lastSymb) + assert.isNumber(trade.execAmount) + assert.equal(trade.execAmount, execAmount) + assert.isNumber(trade.execPrice) + assert.equal(trade.execPrice, execPrice) + + assert.instanceOf(trade.buyFilledAmount, BigNumber) + assert.equal(trade.buyFilledAmount.toNumber(), buyFilledAmount) +} From 3ad7e1df4549841f6d89b941ccce17ece6f11dea Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 27 Jun 2024 12:11:32 +0300 Subject: [PATCH 4/5] Add test case to test sale trades with realized profit --- .../helpers/__test__/test-cases/index.js | 6 +++- .../test-sale-trades-with-realized-profit.js | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-sale-trades-with-realized-profit.js diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js index c6143058..b8835125 100644 --- a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/index.js @@ -3,7 +3,11 @@ const testBuyTradesWithUnrealizedProfit = require( './test-buy-trades-with-unrealized-profit' ) +const testSaleTradesWithRealizedProfit = require( + './test-sale-trades-with-realized-profit' +) module.exports = { - testBuyTradesWithUnrealizedProfit + testBuyTradesWithUnrealizedProfit, + testSaleTradesWithRealizedProfit } diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-sale-trades-with-realized-profit.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-sale-trades-with-realized-profit.js new file mode 100644 index 00000000..4ec0a695 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/test-cases/test-sale-trades-with-realized-profit.js @@ -0,0 +1,33 @@ +'use strict' + +const { assert } = require('chai') + +module.exports = (arr, index, props) => { + const trade = arr[index] + const { + asset, + amount, + mtsAcquired, + mtsSold, + proceeds, + cost, + gainOrLoss + } = props ?? {} + + assert.isObject(trade) + + assert.isString(trade.asset) + assert.equal(trade.asset, asset) + assert.isNumber(trade.amount) + assert.equal(trade.amount, amount) + assert.isNumber(trade.mtsAcquired) + assert.equal(trade.mtsAcquired, mtsAcquired) + assert.isNumber(trade.mtsSold) + assert.equal(trade.mtsSold, mtsSold) + assert.isNumber(trade.proceeds) + assert.equal(trade.proceeds, proceeds) + assert.isNumber(trade.cost) + assert.equal(trade.cost, cost) + assert.isNumber(trade.gainOrLoss) + assert.equal(trade.gainOrLoss, gainOrLoss) +} From d018a423d215a8f05116cfc5e970010987bc8813 Mon Sep 17 00:00:00 2001 From: Vladimir Voronkov Date: Thu, 27 Jun 2024 12:13:26 +0300 Subject: [PATCH 5/5] Add unit test for core look-up-trades fn --- .../helpers/__test__/look-up-trades.spec.js | 404 ++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 workers/loc.api/sync/transaction.tax.report/helpers/__test__/look-up-trades.spec.js diff --git a/workers/loc.api/sync/transaction.tax.report/helpers/__test__/look-up-trades.spec.js b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/look-up-trades.spec.js new file mode 100644 index 00000000..1f91ce26 --- /dev/null +++ b/workers/loc.api/sync/transaction.tax.report/helpers/__test__/look-up-trades.spec.js @@ -0,0 +1,404 @@ +'use strict' + +const { assert } = require('chai') + +const lookUpTrades = require('../look-up-trades') +const { + mockTradesForNextYear, + mockTrades, + getMockedTrades +} = require('./helpers') +const { + testBuyTradesWithUnrealizedProfit, + testSaleTradesWithRealizedProfit +} = require('./test-cases') + +describe('lookUpTrades helper for trx tax report', () => { + it('Lookup buy trx with unrealized profit, LIFO strategy', async function () { + const { + buyTradesWithUnrealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: false, + isBackIterativeBuyLookUp: false, + isBuyTradesWithUnrealizedProfitRequired: true, + isNotGainOrLossRequired: true + } + ) + + assert.isArray(buyTradesWithUnrealizedProfit) + assert.equal(buyTradesWithUnrealizedProfit.length, 5) + + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 0, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 5, 11), + firstSymb: 'ETH', + lastSymb: 'UST', + execAmount: -1, + execPrice: 2_800, + buyFilledAmount: 100 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 1, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 4, 22), + firstSymb: 'ETH', + lastSymb: 'BTC', + execAmount: -1, + execPrice: 0.055, + buyFilledAmount: 0 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 2, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 2, 23), + firstSymb: 'ETH', + lastSymb: 'BTC', + execAmount: 10, + execPrice: 0.05, + buyFilledAmount: 7 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 3, { + isAdditionalTrxMovements: true, + mtsCreate: Date.UTC(2023, 1, 5), + firstSymb: 'BTC', + lastSymb: 'USD', + execAmount: 20, + execPrice: 43_000, + buyFilledAmount: 2.5 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 4, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 0, 10), + firstSymb: 'BTC', + lastSymb: 'USD', + execAmount: 3, + execPrice: 20_000, + buyFilledAmount: 0 + }) + }) + + it('Lookup sale trx with realized profit, LIFO strategy', async function () { + const { + saleTradesWithRealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: false, + isBackIterativeBuyLookUp: false, + isBuyTradesWithUnrealizedProfitRequired: false, + isNotGainOrLossRequired: false + } + ) + + assert.isArray(saleTradesWithRealizedProfit) + assert.equal(saleTradesWithRealizedProfit.length, 7) + + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 0, { + asset: 'UST', + amount: 100, + mtsAcquired: Date.UTC(2023, 5, 11), + mtsSold: Date.UTC(2023, 6, 21), + proceeds: 105, + cost: 111, + gainOrLoss: -6 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 1, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 5, 11), + proceeds: 3_110, + cost: 2_601, + gainOrLoss: 509 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 2, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 4, 22), + proceeds: 2_650, + cost: 2_601, + gainOrLoss: 49 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 3, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 4, 10), + proceeds: 2_000, + cost: 2_601, + gainOrLoss: -601 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 4, { + asset: 'ETH', + amount: 2, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 3, 10), + proceeds: 6_400, + cost: 5_202, + gainOrLoss: 1_198 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 5, { + asset: 'BTC', + amount: 0.5, + mtsAcquired: Date.UTC(2023, 1, 5), + mtsSold: Date.UTC(2023, 2, 23), + proceeds: 25_000, + cost: 21_500, + gainOrLoss: 3_500 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 6, { + asset: 'BTC', + amount: 2, + mtsAcquired: Date.UTC(2023, 1, 5), + mtsSold: Date.UTC(2023, 2, 3), + proceeds: 66_000, + cost: 86_000, + gainOrLoss: -20_000 + }) + }) + + it('Lookup buy trx with unrealized profit, FIFO strategy', async function () { + const { + buyTradesWithUnrealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: true, + isBackIterativeBuyLookUp: true, + isBuyTradesWithUnrealizedProfitRequired: true, + isNotGainOrLossRequired: true + } + ) + + assert.isArray(buyTradesWithUnrealizedProfit) + assert.equal(buyTradesWithUnrealizedProfit.length, 5) + + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 0, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 5, 11), + firstSymb: 'ETH', + lastSymb: 'UST', + execAmount: -1, + execPrice: 2_800, + buyFilledAmount: 100 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 1, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 4, 22), + firstSymb: 'ETH', + lastSymb: 'BTC', + execAmount: -1, + execPrice: 0.055, + buyFilledAmount: 0 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 2, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 2, 23), + firstSymb: 'ETH', + lastSymb: 'BTC', + execAmount: 10, + execPrice: 0.05, + buyFilledAmount: 7 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 3, { + isAdditionalTrxMovements: true, + mtsCreate: Date.UTC(2023, 1, 5), + firstSymb: 'BTC', + lastSymb: 'USD', + execAmount: 20, + execPrice: 43_000, + buyFilledAmount: 0 + }) + testBuyTradesWithUnrealizedProfit(buyTradesWithUnrealizedProfit, 4, { + isAdditionalTrxMovements: false, + mtsCreate: Date.UTC(2023, 0, 10), + firstSymb: 'BTC', + lastSymb: 'USD', + execAmount: 3, + execPrice: 20_000, + buyFilledAmount: 2.5 + }) + }) + + it('Lookup sale trx with realized profit, FIFO strategy', async function () { + const { + saleTradesWithRealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: true, + isBackIterativeBuyLookUp: true, + isBuyTradesWithUnrealizedProfitRequired: false, + isNotGainOrLossRequired: false + } + ) + + assert.isArray(saleTradesWithRealizedProfit) + assert.equal(saleTradesWithRealizedProfit.length, 7) + + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 0, { + asset: 'UST', + amount: 100, + mtsAcquired: Date.UTC(2023, 5, 11), + mtsSold: Date.UTC(2023, 6, 21), + proceeds: 105, + cost: 111, + gainOrLoss: -6 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 1, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 5, 11), + proceeds: 3_110, + cost: 2_601, + gainOrLoss: 509 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 2, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 4, 22), + proceeds: 2_650, + cost: 2_601, + gainOrLoss: 49 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 3, { + asset: 'ETH', + amount: 1, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 4, 10), + proceeds: 2_000, + cost: 2_601, + gainOrLoss: -601 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 4, { + asset: 'ETH', + amount: 2, + mtsAcquired: Date.UTC(2023, 2, 23), + mtsSold: Date.UTC(2023, 3, 10), + proceeds: 6_400, + cost: 5_202, + gainOrLoss: 1_198 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 5, { + asset: 'BTC', + amount: 0.5, + mtsAcquired: Date.UTC(2023, 0, 10), + mtsSold: Date.UTC(2023, 2, 23), + proceeds: 25_000, + cost: 10_000, + gainOrLoss: 15_000 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 6, { + asset: 'BTC', + amount: 2, + mtsAcquired: Date.UTC(2023, 0, 10), + mtsSold: Date.UTC(2023, 2, 3), + proceeds: 66_000, + cost: 40_000, + gainOrLoss: 26_000 + }) + }) + + it('Lookup sale trx with realized profit considering prev year, LIFO strategy', async function () { + const { + buyTradesWithUnrealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: false, + isBackIterativeBuyLookUp: false, + isBuyTradesWithUnrealizedProfitRequired: true, + isNotGainOrLossRequired: true + } + ) + const _mockTradesForNextYear = getMockedTrades(mockTradesForNextYear) + _mockTradesForNextYear.push(...buyTradesWithUnrealizedProfit) + + const { + saleTradesWithRealizedProfit + } = await lookUpTrades( + _mockTradesForNextYear, + { + isBackIterativeSaleLookUp: false, + isBackIterativeBuyLookUp: false, + isBuyTradesWithUnrealizedProfitRequired: false, + isNotGainOrLossRequired: false + } + ) + + assert.isArray(saleTradesWithRealizedProfit) + assert.equal(saleTradesWithRealizedProfit.length, 2) + + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 0, { + asset: 'UST', + amount: 200, + mtsAcquired: Date.UTC(2023, 5, 11), + mtsSold: Date.UTC(2024, 3, 27), + proceeds: 196, + cost: 222, + gainOrLoss: -26 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 1, { + asset: 'BTC', + amount: 5, + mtsAcquired: Date.UTC(2023, 1, 5), + mtsSold: Date.UTC(2024, 2, 17), + proceeds: 305_000, + cost: 220_275, + gainOrLoss: 84_725 + }) + }) + + it('Lookup sale trx with realized profit considering prev year, FIFO strategy', async function () { + const { + buyTradesWithUnrealizedProfit + } = await lookUpTrades( + getMockedTrades(mockTrades), + { + isBackIterativeSaleLookUp: true, + isBackIterativeBuyLookUp: true, + isBuyTradesWithUnrealizedProfitRequired: true, + isNotGainOrLossRequired: true + } + ) + const _mockTradesForNextYear = getMockedTrades(mockTradesForNextYear) + _mockTradesForNextYear.push(...buyTradesWithUnrealizedProfit) + + const { + saleTradesWithRealizedProfit + } = await lookUpTrades( + _mockTradesForNextYear, + { + isBackIterativeSaleLookUp: true, + isBackIterativeBuyLookUp: true, + isBuyTradesWithUnrealizedProfitRequired: false, + isNotGainOrLossRequired: false + } + ) + + assert.isArray(saleTradesWithRealizedProfit) + assert.equal(saleTradesWithRealizedProfit.length, 2) + + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 0, { + asset: 'UST', + amount: 200, + mtsAcquired: Date.UTC(2023, 5, 11), + mtsSold: Date.UTC(2024, 3, 27), + proceeds: 196, + cost: 222, + gainOrLoss: -26 + }) + testSaleTradesWithRealizedProfit(saleTradesWithRealizedProfit, 1, { + asset: 'BTC', + amount: 5, + mtsAcquired: Date.UTC(2023, 1, 5), + mtsSold: Date.UTC(2024, 2, 17), + proceeds: 305_000, + cost: 215_000, + gainOrLoss: 90_000 + }) + }) +})