Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuring day vault PnL starts. #2570

Merged
merged 2 commits into from
Nov 14, 2024

Conversation

vincentwschau
Copy link
Contributor

@vincentwschau vincentwschau commented Nov 14, 2024

Changelist

Allow setting a config var to determine the day vault PnL should start from.
Only queries for PnL data points created past the specified date, and adjusts the total pnl of each point by subtracting the pnl of the start date.

Test Plan

Unit tests.

Author/Reviewer Checklist

  • If this PR has changes that result in a different app state given the same prior state and transaction list, manually add the state-breaking label.
  • If the PR has breaking postgres changes to the indexer add the indexer-postgres-breaking label.
  • If this PR isn't state-breaking but has changes that modify behavior in PrepareProposal or ProcessProposal, manually add the label proposal-breaking.
  • If this PR is one of many that implement a specific feature, manually label them all feature:[feature-name].
  • If you wish to for mergify-bot to automatically create a PR to backport your change to a release branch, manually add the label backport/[branch-name].
  • Manually add any of the following labels: refactor, chore, bug.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new function to retrieve the latest PnL ticks for subaccounts based on a specified date.
    • Added a configuration parameter for setting the vault PnL start date.
  • Improvements

    • Enhanced PnL tick retrieval by incorporating date filtering and adjustment logic for accurate calculations.
    • Expanded test coverage for edge cases related to PnL tick retrieval.
  • Bug Fixes

    • Updated test cases to better handle edge scenarios and ensure accurate PnL calculations based on the new start date parameter.

@vincentwschau vincentwschau requested a review from a team as a code owner November 14, 2024 21:10
Copy link
Contributor

coderabbitai bot commented Nov 14, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes in this pull request enhance the functionality and testing of PnL tick retrieval in the indexer module. A new method for retrieving the latest PnL ticks for subaccounts at specified dates is introduced, along with modifications to existing methods for improved date filtering. The test suite is expanded to cover edge cases and ensure accuracy in PnL calculations. Additionally, a new configuration parameter for the vault's PnL start date is added, affecting how PnL is calculated in related controllers.

Changes

File Path Change Summary
indexer/packages/postgres/__tests__/stores/pnl-ticks-table.test.ts Added new test cases for retrieving latest PnL ticks with date filtering; refined existing tests for accuracy.
indexer/packages/postgres/src/stores/pnl-ticks-table.ts Introduced getLatestPnlTick method; updated getPnlTicksAtIntervals to include earliestDate parameter for filtering.
indexer/services/comlink/__tests__/controllers/api/v4/vault-controller.test.ts Added constant for previous vault PnL start date; updated tests to use a fixed start date for PnL calculations.
indexer/services/comlink/src/config.ts Added new configuration parameter VAULT_PNL_START_DATE with a default value.
indexer/services/comlink/src/controllers/api/v4/vault-controller.ts Added adjustVaultPnlTicks and getVautlPnlStartDate methods; updated PnL tick retrieval logic to include adjustments.

Possibly related PRs

Suggested reviewers

  • shrenujb

🐇 In the land of ticks and time so bright,
New tests and methods take their flight.
With dates in hand, we fetch with glee,
Adjusting PnL, as precise as can be!
So hop along, let changes flow,
To better vaults, we gladly go! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (5)
indexer/services/comlink/src/config.ts (1)

65-65: Consider enhancing date handling robustness

To improve the robustness of the date configuration:

  1. Add runtime validation of the date string format
  2. Make the timezone handling more explicit in the parameter name
  3. Add JSDoc comments to document the expected format and timezone

Consider applying this enhancement:

+ /** 
+  * UTC start date for vault PnL calculations.
+  * Must be in ISO 8601 format: YYYY-MM-DDThh:mm:ssZ
+  */
- VAULT_PNL_START_DATE: parseString({ default: '2024-01-01T00:00:00Z' }),
+ VAULT_PNL_START_DATE_UTC: parseString({
+   default: '2024-01-01T00:00:00Z',
+   validate: (value: string) => {
+     if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/.test(value)) {
+       throw new Error('Invalid date format. Expected: YYYY-MM-DDThh:mm:ssZ');
+     }
+     return value;
+   },
+ }),
indexer/packages/postgres/src/stores/pnl-ticks-table.ts (1)

469-473: LGTM with a minor security suggestion!

The changes to getPnlTicksAtIntervals look good:

  • Early return for empty subaccountIds is an optimization
  • Proper UTC conversion for timestamp comparison

Consider using parameterized queries instead of string interpolation for the earliestDate to prevent potential SQL injection, even though the DateTime type provides some safety.

-        "blockTime" >= '${earliestDate.toUTC().toISO()}'::timestamp AND
+        "blockTime" >= :earliestDate AND

Also applies to: 501-501

indexer/services/comlink/__tests__/controllers/api/v4/vault-controller.test.ts (2)

145-148: Consider enhancing test coverage and documentation.

While the test cases effectively verify the start date functionality, consider these improvements:

  1. Add a comment explaining why 10000 is subtracted from the total PnL (is this the PnL value at the start date?)
  2. Add test cases for edge cases:
    • Start date after all PnL ticks
    • Start date between PnL ticks
    • Invalid start date format

Also applies to: 154-170


Line range hint 516-627: Consider refactoring the test helper function.

The createPnlTicks function could be improved for better maintainability:

  1. Consider extracting the PnL adjustment logic into the helper function:
 async function createPnlTicks(
   createMainSubaccountPnlTicks: boolean = false,
+  startDate?: string,
 ): Promise<PnlTicksFromDatabase[]> {
   const createdTicks: PnlTicksFromDatabase[] = await Promise.all([/*...*/]);
+  if (startDate !== undefined) {
+    for (const createdPnlTick of createdTicks) {
+      createdPnlTick.totalPnl = Big(createdPnlTick.totalPnl).sub('10000').toFixed();
+    }
+  }
   return createdTicks;
 }
  1. Add JSDoc comments explaining:
    • The significance of each time point (twoDaysAgo, currentDay, etc.)
    • The purpose of the PnL adjustment when a start date is provided
indexer/services/comlink/src/controllers/api/v4/vault-controller.ts (1)

339-358: Consider refactoring duplicated logic in PnL ticks retrieval

The code for fetching and adjusting PnL ticks in getVaultSubaccountPnlTicks and getLatestPnlTick is similar. To adhere to the DRY principle, consider refactoring this logic into a shared helper function.

Also applies to: 555-574

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between de6d106 and d9a66d5.

📒 Files selected for processing (5)
  • indexer/packages/postgres/__tests__/stores/pnl-ticks-table.test.ts (2 hunks)
  • indexer/packages/postgres/src/stores/pnl-ticks-table.ts (4 hunks)
  • indexer/services/comlink/__tests__/controllers/api/v4/vault-controller.test.ts (4 hunks)
  • indexer/services/comlink/src/config.ts (1 hunks)
  • indexer/services/comlink/src/controllers/api/v4/vault-controller.ts (5 hunks)
🔇 Additional comments (6)
indexer/services/comlink/src/config.ts (1)

65-65: Verify if future default date is intentional

The default value is set to '2024-01-01T00:00:00Z', which is a future date. This could affect PnL calculations by excluding all current data points. Please verify if this is the intended behavior.

✅ Verification successful

Based on the search results, I can see that:

  1. The VAULT_PNL_START_DATE config is used in vault-controller.ts to determine the start date for vault PnL calculations
  2. The tests explicitly set this value to '2020-01-01T00:00:00Z' for testing purposes
  3. The default value of '2024-01-01T00:00:00Z' appears to be intentional as it's used in production code

Let me verify the vault PnL calculation logic to understand if this future date is indeed intentional.


Let me check the vault PnL query implementation to understand how the start date is used.


Let me try a different search pattern to find the PnL query implementation.


Let me try one final search pattern to understand the vault PnL implementation.


After analyzing the code, I can now provide a definitive response about the future default date.

Future default date is intentional and correct

The future default date of '2024-01-01T00:00:00Z' is intentionally set as it's used as a configuration parameter to control when vault PnL tracking begins. This is verified by:

  1. The code in vault-controller.ts uses this date as a starting point for querying PnL data through getVaultPnlStartDate()
  2. Tests explicitly override this value to '2020-01-01T00:00:00Z' for testing historical data
  3. The implementation adjusts PnL calculations by subtracting the PnL values from this start date, ensuring accurate PnL tracking from the configured date forward
  4. The date is used consistently across multiple functions including getVaultSubaccountPnlTicks() and getLatestPnlTick()
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any hardcoded references to this date in tests or related files
# that might provide context about the chosen default date

echo "Searching for date string references in vault-related files..."
rg -A 5 "2024-01-01|VAULT_PNL_START_DATE" --type ts

echo "Searching for PnL calculation logic that uses this config..."
ast-grep --pattern 'config.VAULT_PNL_START_DATE'

Length of output: 70551


Script:

#!/bin/bash
# Search for vault PnL calculation logic to understand how the start date is used
rg -A 10 "historicalPnl|totalPnl|calculatePnl" --type ts indexer/services/comlink/src/

Length of output: 15305


Script:

#!/bin/bash
# Search for the SQL query that fetches vault PnL data to see how the start date is used
rg -B 5 -A 10 "getVaultPnlTicks|getPnlTicks.*vault" --type ts indexer/services/comlink/src/

Length of output: 93


Script:

#!/bin/bash
# Search for PnL-related database queries and the usage of start date
echo "Searching for PnL database queries..."
rg -B 5 -A 10 "FROM pnl_ticks.*WHERE" --type sql indexer/services/comlink/src/

echo "Searching for start date usage in vault controller..."
rg -B 10 -A 5 "getVaultPnlStartDate|startDate.*vault" --type ts indexer/services/comlink/src/

Length of output: 378


Script:

#!/bin/bash
# Search for files containing both vault and PnL related code
echo "Searching for vault PnL implementation files..."
fd -e ts -e sql . indexer/services/comlink/src/ -x grep -l "vault.*pnl\|pnl.*vault" {} \; -x cat {}

echo "Searching for files referencing the start date..."
rg -l "VAULT_PNL_START_DATE" --type ts | xargs cat

Length of output: 79111

indexer/packages/postgres/src/stores/pnl-ticks-table.ts (1)

515-550: LGTM with optimization suggestions!

The new getLatestPnlTick function is well-implemented:

  • Efficient use of DISTINCT ON for latest record retrieval
  • Proper early return optimization
  • Clear and type-safe parameters

Suggestions:

  1. Use parameterized queries for SQL injection prevention
  2. Ensure proper indexing for optimal query performance

Consider this safer implementation:

-      "blockTime" <= '${beforeOrAt.toUTC().toISO()}'::timestamp
+      "blockTime" <= :beforeOrAt
✅ Verification successful

Query is properly optimized with required indexes

The codebase has both required indexes for optimal query performance:

  • pnl_ticks_blocktime_index on blockTime column
  • pnl_ticks_subaccountid_index on subaccountId column

These indexes will ensure efficient execution of the DISTINCT ON query with its ORDER BY clause. The only remaining suggestion is to use parameterized queries for SQL injection prevention.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify indexes exist for the query's ORDER BY columns

# Check for indexes on blockTime and subaccountId columns
psql -c "\d+ pnl_ticks" | grep -E "blockTime|subaccountId"

Length of output: 132


Script:

#!/bin/bash
# Let's try to find the schema definition or migration files to check for indexes
fd -e sql -e ts migration | xargs rg -l "CREATE.*INDEX.*pnl_ticks"

# Also search for table creation to see column definitions
fd -e sql -e ts migration | xargs rg -l "CREATE.*TABLE.*pnl_ticks"

Length of output: 137


Script:

#!/bin/bash
# Let's try a broader search for any files containing pnl_ticks table definition
rg -A 10 "CREATE.*TABLE.*pnl_ticks" 

# Also search for any index definitions related to pnl_ticks
rg "CREATE.*INDEX.*pnl_ticks"

# Search for knex migrations related to pnl_ticks
fd -e ts | xargs rg "knex.*createTable.*pnl_ticks"

Length of output: 552

indexer/packages/postgres/__tests__/stores/pnl-ticks-table.test.ts (2)

463-463: LGTM: Proper implementation of earliest date filtering

The addition of the earliestDate parameter correctly tests the filtering of PnL ticks based on a start date, which aligns with the PR's objective.


486-512: LGTM: Comprehensive test coverage for getLatestPnlTick

The new test cases provide thorough coverage of the getLatestPnlTick functionality:

  • Testing successful retrieval of latest PnL ticks
  • Handling dates before any PnL data exists
  • Handling empty subaccount lists

The tests are well-structured and properly validate the edge cases.

indexer/services/comlink/__tests__/controllers/api/v4/vault-controller.test.ts (1)

46-46: LGTM: Configuration management follows best practices.

The code properly manages the VAULT_PNL_START_DATE configuration by:

  1. Storing the previous value
  2. Setting a default value before tests
  3. Restoring the original value after tests

Also applies to: 62-63, 132-132

indexer/services/comlink/src/controllers/api/v4/vault-controller.ts (1)

744-765: Implementation of adjustVaultPnlTicks is correct

The adjustVaultPnlTicks function accurately adjusts the totalPnl values for each subaccount. The logic is sound and the implementation is clean.

Comment on lines +350 to +351
getVautlPnlStartDate(),
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in function name 'getVautlPnlStartDate'

The function name getVautlPnlStartDate is misspelled. It should be getVaultPnlStartDate. Please update the function name and all its usages accordingly.

Apply this diff to correct the function name and its usages:

-function getVautlPnlStartDate(): DateTime {
+function getVaultPnlStartDate(): DateTime {
  const startDate: DateTime = DateTime.fromISO(config.VAULT_PNL_START_DATE).toUTC();
  return startDate;
}

...

-        getVautlPnlStartDate(),
+        getVaultPnlStartDate(),

...

-          getVautlPnlStartDate().plus({ minutes: 10 }),
+          getVaultPnlStartDate().plus({ minutes: 10 }),

...

-          getVautlPnlStartDate(),
+          getVaultPnlStartDate(),

...

-          getVautlPnlStartDate().plus({ minutes: 10 }),
+          getVaultPnlStartDate().plus({ minutes: 10 }),

Also applies to: 356-357, 566-567, 572-573, 799-802

@vincentwschau vincentwschau merged commit 4633b85 into main Nov 14, 2024
16 checks passed
@vincentwschau vincentwschau deleted the vincentc/configure-vault-pnl-start branch November 14, 2024 21:50
@vincentwschau
Copy link
Contributor Author

@Mergifyio backport release/indexer/v7.x

Copy link
Contributor

mergify bot commented Nov 14, 2024

backport release/indexer/v7.x

✅ Backports have been created

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants