Skip to content

Wheeler v2 draft model#17

Open
MarkT1065 wants to merge 9 commits into
mainfrom
transactions_erd
Open

Wheeler v2 draft model#17
MarkT1065 wants to merge 9 commits into
mainfrom
transactions_erd

Conversation

@MarkT1065
Copy link
Copy Markdown
Owner

@antamy PTAL

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 2, 2025

You took a different approach focusing on the data model. I went more top down and Claude (web) produced a very similar, but not as detailed table structure. Did you use Claude Code for yours?

I'm not sure how I should share my file - do I just add it to this commentary?

@MarkT1065
Copy link
Copy Markdown
Owner Author

I always go "bottom up" in terms of data. you can comment on this PR directly, claude can probably do it somehow too, and/or you can pull the branch and submit PRs to this branch.

Ideally, if the "spec" is correct with data model with all use cases accounted for, then it's easy to generate the next layers up.

@MarkT1065
Copy link
Copy Markdown
Owner Author

MarkT1065 commented Nov 2, 2025

Did you use Claude Code for yours?

Yes, this entire repo has been built by Claude Code. It's a great side project to learn with. I'm purposefully trying to keep my hands out of the code.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 2, 2025

I always go "bottom up" in terms of data. you can comment on this PR directly, claude can probably do it somehow too, and/or you can pull the branch and submit PRs to this branch.

Ideally, if the "spec" is correct with data model with all use cases accounted for, then it's easy to generate the next layers up.

For now, I've just added two files to this comment. I'm not proficient enough with git to figure out how to do all the pushing and pulling! The architecture file is what I originally came up with. I gave your spec to Claude and asked for a comparison and suggested merge approach, and that is attached too. The synopsis is to go with your data model and add in some additional functionality that I specified.

wheeler_architecture_v2 - antamy.md
wheeler_spec_comparison.md

Did you use Claude Code for yours?

Yes, this entire repo has been built by Claude Code. It's a great side project to learn with. I'm purposefully trying to keep my hands out of the code.

I originally used the web version, but then paid for Pro to get access to Claude Code inside VS Code. The web version did tell me that it would be better suited for architectural discussions and planning, the results of which can then be given to Claude Code for implementation, so that is what I did to create these documents.

@MarkT1065
Copy link
Copy Markdown
Owner Author

I agree with "### Option A: Start with Original Author's Base + Add Our Features". If we start with the data model specifically, we can account for all the use cases, have explicit tests, and know it all works before we leave the data layer.

During a previous refactor, I had Claude identify all the "panels" across all the views and put them into a refactor plan. i went through them one by one and ensured each had a handler + test. I'd like to do the same for a v2 refactor. We can make a list of all panels, write out what they should do, and refactor each one in place. The whole application would continue to work.

With the right data model beneath + data access layer, you can add all the features you want (different "campaigns" and other ways to focus the data).

Comment thread wheeler_v2_spec.md
@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 2, 2025

I agree with "### Option A: Start with Original Author's Base + Add Our Features". If we start with the data model specifically, we can account for all the use cases, have explicit tests, and know it all works before we leave the data layer.

During a previous refactor, I had Claude identify all the "panels" across all the views and put them into a refactor plan. i went through them one by one and ensured each had a handler + test. I'd like to do the same for a v2 refactor. We can make a list of all panels, write out what they should do, and refactor each one in place. The whole application would continue to work.

With the right data model beneath + data access layer, you can add all the features you want (different "campaigns" and other ways to focus the data).

Do you want to work on refining the data model and I can work with Claude to create the updated list of panels and their high level functionality? We can then take a view on sequencing and have Claude merge all of that into a v2 architecture spec with an implementation plan.

I'm not entirely clear on how we have 2 Claudes collaborate on one document.

@MarkT1065
Copy link
Copy Markdown
Owner Author

SGTM. I will do a detailed plan for the model + data layer + tests. You can make a plan with each of the panels and their requirements. Two different PRs, two different documents.

@MarkT1065
Copy link
Copy Markdown
Owner Author

@antamy Claude added a plan for detailed SQL data model w/ migrations.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 3, 2025

When we think about Account, is it necessary to have an account type? Taxable / non-taxable seems to be outside the scope of the application and could be reflected in an account's name. Accounts should just be flexible containers (folders) for grouping a set of instruments and associated trades and campaigns.

@MarkT1065
Copy link
Copy Markdown
Owner Author

Claude added "account_type" and I thought the same thing as you. I'll remove it.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 6, 2025

Data requirements for supporting wheels:

  • capture implied volatility and delta for the options trades
  • capture price of the stock when the trade (CSP, CC, assignment) occurs
  • wheel tables (see below), with FK relationships to the transactions

For each Wheel, this is what Claude came up with, based on the prototype where I used a JSON data store:

// Wheel represents a wheel campaign
type Wheel struct {
	ID                   
	AccountID  
	Symbol             
	Status      // active, closed
	CreatedAt    
	ClosedAt     
	ContractSize  
	TargetStrikeStrategy 
	Notes    
	Summary    
	Trades  []WheelTrade 
}

// WheelSummary contains aggregated statistics for a wheel
type WheelSummary struct {
	TotalPremiumCollected 
	TotalCapitalGains   
	TotalDividends   
	TotalProfit     
	CurrentStockPosition  
	CurrentCashSecured 
	NumberOfCycles     
	NumberOfPutTrades  
	NumberOfCallTrades  
	NumberOfAssignments  
	NumberOfExpirations   
	NumberOfRolls   
}

// WheelTrade represents a trade in a wheel campaign
type WheelTrade struct {
	ID             
	WheelID       
	TradeType     
	SequenceNumber 
	CycleNumber 
	OpenDate      
	ExpirationDate  
	CloseDate     
	Strike    
	Contracts  
	Premium    
	Commission 
	StockPrice  
	AssignmentPrice
	NetProceeds  
	Status     
	Outcome   
	Notes     
	RollDetails     *RollDetails
}

// RollDetails contains information about rolled positions
type RollDetails struct {
	ClosedTradeID  
	ClosePremium  
	CloseCommission
	NetRollCredit  
}

The idea here is to explicitly define your wheels (stock, # of contracts, wheel strategy etc.) within an account (which may just be a pile of cash), then track the execution and performance of the wheels. Trades are entered from the wheel pages and tracked in sequence (so we would need to have a FK relationship to the transaction). The UI provides a simplified data entry which is context aware based on the state of the wheel. IV and delta can be tracked if required, along with stock price at the time of trade. Manipulating the trades through the Options and Symbols menus would not be allowed.

@MarkT1065
Copy link
Copy Markdown
Owner Author

@antamy I removed "account_type", per comments above, and also added a Trade table to the ERD. it rounds out the model.

@MarkT1065
Copy link
Copy Markdown
Owner Author

Also, re: your comments above about tracking a "wheel campaign" ... I think I understand. We'd need some way of grouping some trades together for some arbitrary reason. Perhaps after the base data model is improved, we can work on adding a "Strategies" view that contains the various campaigns that were tried, what their results were, etc.?

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 8, 2025

Also, re: your comments above about tracking a "wheel campaign" ... I think I understand. We'd need some way of grouping some trades together for some arbitrary reason. Perhaps after the base data model is improved, we can work on adding a "Strategies" view that contains the various campaigns that were tried, what their results were, etc.?

I'm traveling right now, however I think my prototype PR is up to date with my latest changes. If you pull that you'll see the initial concept. Here's a screenshot.

image

@MarkT1065
Copy link
Copy Markdown
Owner Author

@antamy the last commit on this PR cleans up the schema.

Claude's migration plan looks pretty decent, but I'm wary it can do it all like that in one shot.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 10, 2025

@antamy the last commit on this PR cleans up the schema.

Claude's migration plan looks pretty decent, but I'm wary it can do it all like that in one shot.

did you upload the plan? does it have an assessment of how invasive the new schema will be to the codebase? let me know how you want to proceed.

@MarkT1065
Copy link
Copy Markdown
Owner Author

yes, claude implemented a migration plan in the markdown doc. I reviewed it pretty carefully, made edits (some of my commits), and I curious to try it's approach piecemeal. A second set of eyes couldn't hurt. There's ERD/data model/use cases/migration plan in the doc.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 11, 2025

I read through the v2 spec with the database migration plan, I didn't see any functional migration plan. It seems fine, however since the application needs to be rebuilt for the new schema the database migration would seem to be the last piece to implement. I was envisaging cloning the existing codebase, implementing the new database and the new functionality to CRUD Accounts. Then tackle vertical slices - Symbols, Treasuries, cash, Stocks, Options - before moving on to the analytical views and utility functions. I think, but haven't confirmed, that the vertical slices are pretty much independent, so we could work on them in parallel. We could have Claude create this work item list and then we can pick the next item to work on based on availability.

How did you approach building the original codebase? Was it slice by slice, or did you establish the database, data access and API layers and then the major functions?

@MarkT1065
Copy link
Copy Markdown
Owner Author

Claude's "migration" is still to be implemented, but I think the SQL in the markdown needing to adjust the schema appears correct. I'm more curious about its coalesce statements that attempts to backfill data, like transactions. Other data needs to be filled in, like filling out trades with both ends, perhaps recording assignment, etc. according to history. I have hundreds of trades to migrate. Even if there's a v2 codebase, it'd require some parsing of CSVs exported from v1 with the same kind of logic to pair up trades and such into the new schema.

It seems like a good schema w/ data layer and migration to new "trades" backfilled with transactions is the minimally viable thing. The default "trade type" would be the current wheel strategies that are hardcoded. The UI would continue to work as-is, because the old data model remains.

If that all works, it's safe to develop and test the UI separately from the backend.

@MarkT1065
Copy link
Copy Markdown
Owner Author

My preference would be to refactor the existing application in a way that works the entire time. I have a lot of current/active data in my instance of Wheeler and I'm relying on it. But my only concern about that is the migration to the improved data model. So long as that's Easy™, Claude makes code (persistence and graphs) pretty easy.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 11, 2025

Other data needs to be filled in, like filling out trades with both ends, perhaps recording assignment, etc. according to history. I have hundreds of trades to migrate. Even if there's a v2 codebase, it'd require some parsing of CSVs exported from v1 with the same kind of logic to pair up trades and such into the new schema.

I hadn't thought too much about that, however don't we already have all the data for this? Each current trade is opened (sell to open) and then closed with a premium paid (buy to close) or just closed (expired). Matching up an expiration with a stock buy or sell (assignment) does seem a little tricky - I don't think I have a solution for that.

It seems like a good schema w/ data layer and migration to new "trades" backfilled with transactions is the minimally viable thing. The default "trade type" would be the current wheel strategies that are hardcoded. The UI would continue to work as-is, because the old data model remains.

Not sure I understand this, why would the old data model remain?

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 11, 2025

My preference would be to refactor the existing application in a way that works the entire time. I have a lot of current/active data in my instance of Wheeler and I'm relying on it. But my only concern about that is the migration to the improved data model. So long as that's Easy™, Claude makes code (persistence and graphs) pretty easy.

I guess my point was that the migration has to occur at some point. My view is that it would be easier to do that once the v2 transactional functionality is complete, vs at the beginning. Then you can continue to use v1, get v2 off the ground and understand nuances we haven't considered, and then migrate the data. I don't really mind. I've got several hundred transactions in it now and if we do migration first, I would probably continue with v1 and run fresh v1 to v2 migrations as the codebase takes shape.

@MarkT1065
Copy link
Copy Markdown
Owner Author

I suppose the first question is "refactor v1 or rewrite as v2?" both require the same data migration. both, in my mind, would tackle the data layer first w/ use cases and tests.

But using v1 data model requires the full migration, I think, whereas build new v2 means v1 can stay as-is while a v2 is built from scratch.

If v1 is refactored, then the same tables will exist. The Options table, for example, exists in both schemas but has more attributes for v2. This can be refactored from v1, if desired. the same UI views can continue to use the Options table with the preexisting attributes while the new ones would be used by v2. Each panel in the UI can change over time to use new data. This is how I envision keeping the whole thing running the whole time.

Or v1 was a learning experience and Claude makes writing new code easier (still takes time to debug and fix everything).

In either case, a well-defined data model that can account for all our use cases is a solid foundation. The UI is just fancy graphs on top of solid data.

@antamy
Copy link
Copy Markdown
Contributor

antamy commented Nov 12, 2025

Ah, I see. I misinterpreted the approach as being to implement the v2 model then on 1st run, convert a v1 database into v2. We can try the re-factor approach and hopefully Claude doesn't create a lot of spaghetti!

I have some time from this Friday thru' Thursday next week to work on this, then I'll be traveling until after Thanksgiving. Do you want to tackle the schema change, then I can work on account and other items?

@MarkT1065
Copy link
Copy Markdown
Owner Author

In some general rough order:

  1. The markdown has Claude's migration logic, but I was guiding what it came up with. I think it's the correct flow for modifying a live schema. I'm not sure about backfilling via coalesce. We might not want to do that. If we're bottom up, this is the bottom-most layer.

  2. Then there's the Go code for implementing migrations, assuming we're going to have more migrations in the future. We'll need to modify many schemas (in the wild that we don't know about) in a backwards compatible way, starting with our own wheeler instances. This is where we apply the SQL we figured out in step 1.

  3. Create the missing models (Account, Trade, etc.). Basic persistence layer with tests.

  4. Express a trade in a test. Implement our use cases in tests. If we can express a complex financial transaction in English in a use case, we can ensure it works in an automated test.

  5. Migrate missing data for trades. Apply default values to any missing attributes because they represent the previously hard-coded wheeler trades. By utilizing the new Trade.trade_type attribute, we can be more expressive.

  6. UI is now broken.

How to fix 6? Implement v2 UI in step 3? But what about existing trades we're managing today in real life?

@MarkT1065
Copy link
Copy Markdown
Owner Author

The current UI is pure CRUD to the database. The HTML forms have some JS validation in them. There is some logic in the handlers and/or model that performs calculations before persistence. This is the "hard-coded" Trade type I mentioned. The logic is throughout the stack and it's built to wheel in one way.

Introducing the Trade table means we can make new UI to open a trade, make updates, close a trade. It's more of a flow (by trade type) than the simple CRUD forms in place today. We take actions on data.

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.

2 participants