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

RFC/one Symbol Profile per interest name #3899

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ceroma
Copy link
Contributor

@ceroma ceroma commented Oct 9, 2024

Currently, each Interest activity creates a new Symbol Profile. This may leave the DB cluttered with multiple single-activity Symbols (see #3381), causing a slowness in portfolio snapshot computation and some difficulty in parsing all symbols in Admin Control > Market Data page.

This is a proposal to keep a single Symbol Profile for each unique name used for an Interest-typed activity. What do you think?

Test Plan:

  1. Create an Interest activity named "AAAA"
  2. Create another Interest activity named "AAAA"
  3. Verify in Market Data that only one Symbol Profile exists for both interest activities
  4. Delete the first "AAAA" Interest activity
  5. Verify the other activity still exists
  6. Verify the "AAAA" Symbol Profile still exists
  7. Delete the second "AAAA" Interest activity
  8. Verify the "AAAA" Symbol Profile got deleted
  9. Create an Interest activity named "BBBB"
  10. Create another Interest activity named "BBBB"
  11. Update one of the activities to be named "CCCC"
  12. Verify one "BBBB" and one "CCCC" activities exist
  13. Verify in Market Data that there are two Symbol Profiles, one for "BBBB" and one for "CCCC"
  14. Rename Symbol Profile "CCCC" to "DDDD" from the Market Data page
  15. Verifify the activity in Activities page shows up as "DDDD" now

Currently, each Interest activity creates a new Symbol Profile. This may leave the DB cluttered with multiple single-activity Symbols (see ghostfolio#3381), causing a slowness in portfolio snapshot computation and some difficulty in parsing all symbols in Admin Control > Market Data page.

This is a proposal to keep a single Symbol Profile for each unique name used for an Interest-typed activity.

Test Plan:
1. Create an Interest activity named "AAAA"
2. Create another Interest activity named "AAAA"
3. Verify in Market Data that only one Symbol Profile exists for both interest activities
4. Delete the first "AAAA" Interest activity
5. Verify the other activity still exists
6. Verify the "AAAA" Symbol Profile still exists
7. Delete the second "AAAA" Interest activity
8. Verify the "AAAA" Symbol Profile got deleted
9. Create an Interest activity named "BBBB"
10. Create another Interest activity named "BBBB"
11. Update one of the activities to be named "CCCC"
12. Verify one "BBBB" and one "CCCC" activities exist
12. Verify in Market Data that there are two Symbol Profiles, one for "BBBB" and one for "CCCC"
13. Rename Symbol Profile "CCCC" to "DDDD" from the Market Data page
14. Verifify the activity in Activities page shows up as "DDDD" now
Copy link
Member

@dtslvr dtslvr left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution, @ceroma.
I have reviewed your RFC and added a few comments.


let symbolProfileSymbol = id;

if (data.type === 'INTEREST') {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it be the same behavior for all types according to #3381 (comment)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure if those comments meant "yeah, they go through the same code path when being created" or "yeah, we should reuse profiles for all those types". Given that I'm not too familiar with how non-INTEREST types are used across the codebase, I felt it was safer to start with just INTERESTs. Should we apply the same logic to all of them then?


if (data.type === 'INTEREST') {
const symbolProfile = await this.prismaService.symbolProfile.findFirst({
orderBy: {
Copy link
Member

Choose a reason for hiding this comment

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

Probably not necessary for findFirst

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does findFirst implicitly picks the first in reverse chronological order? Or you mean it doesn't matter which one we pick if there are multiple with the same name? My intent with picking the last-created here was to leave old data unchanged to avoid any unforeseen issue that could possibly corrupt people's data. For instance, I have many months of "Bank Interest". After these changes, all new "Bank Interest" will be grouped withing the same Symbol Profile, but the old ones will stay as they were.

Copy link
Member

Choose a reason for hiding this comment

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

If where is unique (see my comment on collision below), I think orderBy is not needed

orderBy: {
createdAt: 'desc'
},
where: {
Copy link
Member

Choose a reason for hiding this comment

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

There will be collisions in the cloud setup. A userId (including migration path) is needed to avoid them.

Copy link
Member

Choose a reason for hiding this comment

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

Add currency as below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There will be collisions in the cloud setup. A userId (including migration path) is needed to avoid them.

You mean collisions like users A and B having the same INTEREST named "Bank Interest"? Shouldn't it be the fine, in the same way that it's fine for users A and B to have different activities pertaining the same AAPL symbol, for instance?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe it would work for INTEREST, but I see an issue for ITEM. If you and me both own a Beach House, we could not share the same asset profile because of different historical market prices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, good point! But in that same train of thought, I could see a user having multiple ITEM items with the same name to represent different physical items, right? Should we keep ITEMs as is so as to not break that expected behavior for historical market prices?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we could keep ITEM (and LIABILITY) as is and see them as unique.
As a result there will be one Symbol Profile per INTEREST / FEE?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good to me, I'll update accordingly.
Just to confirm though - do you still think we should have INTEREST/FEE unique per userId or it's ok for them to be globally unique?

Copy link
Member

Choose a reason for hiding this comment

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

I would still do it unique per userId, otherwise if I rename it would also be renamed for you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, in the current implementation that would not happen. See updateOrder below. When you rename a INTEREST order, it will either connect it to an existing SymbolProfile with the new name or create a new SymbolProfile if one doesn't exist with that name.

delete data.SymbolProfile.connect;

const symbolProfile = await this.prismaService.symbolProfile.findFirst({
orderBy: {
Copy link
Member

Choose a reason for hiding this comment

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

Probably not necessary for findFirst

@dtslvr dtslvr linked an issue Oct 17, 2024 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Each interest activity creates a new asset profile
2 participants