-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
205 compare jaws against indices on portfolioview (#236)
* NavBar: make links use a tag * Add endpoint to get portfolio historyu * Fix handleResult so it doesn't nest errors 3 levels * portfolioHistory: Make timestamps to ISO strings * Add params to getPortfolioHistory endpoint * Add very naive calculatePNL * WIP fix test * PNL: Add support for sales split into TP/SL * Portfolio: Add cash box; refactor * Add calculateNAV util * NavBar: use AccountStore instead of AccountContext * Replace NAV calculation with correct one * WIP on trigger-calculate-nav * calculateNAV: Improve tests, add info; update variable names * Add getDateString helper to get YYYY-MM-DD string from any date * Add trigger-calculate-nav endpoint * add endpoint to get daily stats * Rename api/nav -> api/daily-stats, cleanup * BackendService: Add getDailyStats func * Rename trigger nav -> daily-stats * calculatePNL.test: remove empty arrow function fixes build error
- Loading branch information
Showing
20 changed files
with
833 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { db } from "@jaws/services/firestoreService"; | ||
import { DailyStats } from "./dailyStatsMeta"; | ||
export async function getDailyStats({ | ||
startDate, | ||
endDate, | ||
accountId, | ||
}: { | ||
/** Format: YYYY-MM-DD (inclusive) */ | ||
startDate: string; | ||
/** Format: YYYY-MM-DD (inclusive) */ | ||
endDate: string; | ||
accountId: string; | ||
}) { | ||
return ( | ||
await db | ||
.collection("daily-stats") | ||
.where("accountId", "==", accountId) | ||
.where("date", ">=", startDate) | ||
.where("date", "<=", endDate) | ||
.orderBy("date", "asc") | ||
.get() | ||
).docs.map((doc) => doc.data()) as DailyStats[]; | ||
} | ||
|
||
export async function upsertDailyStats(stats: DailyStats) { | ||
return db | ||
.collection("daily-stats") | ||
.doc(generateDocId(stats.accountId, stats.date)) | ||
.set(stats); | ||
} | ||
|
||
function generateDocId(accountId: string, date: string) { | ||
return `${date.replace(/-/g, "")}-${accountId}`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export interface DailyStats { | ||
accountId: string; | ||
nav: number; | ||
shares: number; | ||
date: string; | ||
/** | ||
* TODO: Remove when not needed anymore :) | ||
* @deprecated don't rely on this for anything | ||
*/ | ||
debugInfo?: Record<string, any>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { getDailyStats, upsertDailyStats } from "@jaws/db/dailyStatsEntity"; | ||
import { RawActivity } from "@jaws/services/alpacaMeta"; | ||
import * as alpacaService from "@jaws/services/alpacaService"; | ||
import { calculateNAV } from "@jaws/util/calculateNAV"; | ||
import { getDateString, getTodayWithDashes, ONE_DAY_IN_MS } from "./helpers"; | ||
|
||
export type DayDateString = ``; | ||
|
||
export const calculateTodaysNAV = async (accountId: string) => { | ||
const todayDate = getTodayWithDashes(); | ||
const yesterdaysDate = getDateString({ | ||
date: new Date(Number(new Date(todayDate)) - ONE_DAY_IN_MS), | ||
withDashes: true, | ||
}); | ||
|
||
const [equity, cashActivities, [{ debugInfo, ...yesterdayStats }]] = | ||
await Promise.all([ | ||
alpacaService.getEquity(), | ||
alpacaService.getAccountActivities({ | ||
activity_type: "TRANS", | ||
date: todayDate, | ||
}), | ||
getDailyStats({ | ||
startDate: yesterdaysDate, | ||
endDate: yesterdaysDate, | ||
accountId, | ||
}), | ||
]); | ||
|
||
isNonTradeActivities(cashActivities); | ||
|
||
const netDeposits = cashActivities | ||
.filter((ct) => ct.status !== "canceled") | ||
.reduce((sum, ct) => sum + parseFloat(ct.net_amount), 0); | ||
|
||
const NAV = calculateNAV({ | ||
numShares: yesterdayStats.shares, | ||
equity: parseFloat(equity), | ||
netDeposits, | ||
}); | ||
|
||
return { | ||
equity, | ||
cashActivities, | ||
netDeposits, | ||
yesterdayStats, | ||
...NAV, | ||
todayDate, | ||
yesterdaysDate, | ||
}; | ||
}; | ||
|
||
export const saveTodaysNAV = async () => { | ||
// TODO: Do for all accounts | ||
const { | ||
NAV: nav, | ||
todayDate: date, | ||
newNumShares: shares, | ||
...debugInfo | ||
} = await calculateTodaysNAV("hejare"); | ||
|
||
await upsertDailyStats({ | ||
nav, | ||
accountId: "hejare", | ||
date, | ||
shares, | ||
/** TODO: Remove when not needed anymore :) */ | ||
debugInfo, | ||
}); | ||
|
||
return { nav, date, shares, ...debugInfo }; | ||
}; | ||
|
||
function isNonTradeActivities( | ||
activities: RawActivity[], | ||
): asserts activities is (RawActivity & { net_amount: string })[] { | ||
if (!activities.every((a) => "net_amount" in a)) { | ||
throw new TypeError("Found activity without net_amount"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.