A Windows desktop trade journaling application for tracking trades across multiple markets — crypto, stocks, forex, futures, options, commodities, and more.
Status: Pre-release development (no public release yet)
Internal tracking versions:
OzzTradeDiary0.0.63,OzzTradeDiary.AppInfra0.0.63,OzzTradeDiary.RepositoryContracts0.0.63,OzzTradeDiary.WPF0.0.63,OzzTradeDiary.SQLite0.0.63,OzzTradeDiary.i18n0.0.63
See CHANGELOG.md for release history.
- This project uses icon paths derived from Bootstrap Icons.
- Source:
https://icons.getbootstrap.com - Project repository:
https://github.com/twbs/icons - Version:
v1.13.1 - License:
MIT - SPDX License Identifier:
MIT
- Track trades across multiple markets: Crypto, Stock, Forex, Futures, Options, Commodities, and more
- Long and short trade directions
- Separate order type enums for entries (
EntryOrderType: Market, Limit, StopMarket, StopLimit) and exits (ExitOrderType: Market, Limit, TrailingStop, Stop, StopLimit) - Entry/exit orders, stop-loss, and take-profit levels per trade
- Trade images: attach chart screenshots or web URLs with notes
- Trade filtering and paging with
TradeQueryParameters— supports date ranges, position values, P/L, and risk range filters
- Manage multiple exchanges with optional default currency per exchange
- Manage multiple trading accounts linked to exchanges
- Manage symbols with market type, base/price currency, and exchange association
- Maintenance window for Currency, Exchange, TradingAccount, and Symbol CRUD
- Add, Edit, Save, Refresh, and Delete operations with localized icon-based buttons
- Symbols tab supports text search and exchange-based filtering
- Safe exchange deletion — disabled when exchange is referenced by symbols or trading accounts
- Unsaved-changes confirmation on dialog close for edit dialogs
- Full English and Turkish UI support
- Localized DataAnnotations on model classes for display names and validation messages
- All UI strings sourced from generated resource classes (
ActionStrings,CommonStrings,ErrorStrings,LocalizedStrings,MessageStrings)
- Raw SQLite data access via Microsoft.Data.Sqlite — no ORM
- Repository implementations in
TD.SQLite, contracts inTD.RepositoryContracts - Repositories implemented:
Currency,Exchange,TradingAccount,Symbol,Trade,TradeImage,EntryOrder,StopLossOrder,TakeProfitOrder - Navigation collections auto-loaded for
Exchange(Symbols, TradingAccounts) andTrade(orders, images) - Type-safe decimal SQLite persistence — scaled integers for values,
TEXTfor precision-sensitive price/quantity fields
- Automatic and manual SQLite backup via SQLite BACKUP API
- Backups archived as timestamped ZIP files
- Configurable retention policy with automatic cleanup of old backups
TD.Tools.SeedDemoDataconsole tool for seeding realistic demo crypto trade dataScripts/SeedDemoData.batconvenience launcher — resets and reseeds the debug database- Debug builds use repo-root
SampleData/path to avoid touching user app-data folders - SQLite DDL scripts, localization resources, model classes, and repository generation settings managed by OzzCodeGen
- DPI-aware multi-monitor window positioning
- App version displayed in title bar; Bootstrap Icons for window title bar icons
- UI culture configurable via
AppSettings.UiCulture(BCP-47); falls back to OS culture when empty - Shared platform-agnostic MVVM base classes (
AbstractViewModel,AbstractCommand,AbstractDataErrorInfoVM,AbstractCreateEditVM,AbstractDiaryVM) andAppDataSourcesdependency container inTD.AppInfrafor reuse by WPF and future MAUI frontends App.OnStartupis the single composition root: all repositories are created as named variables, wrapped inAppDataSources(TD.AppInfra.Models), and passed as a single object intoMainWindow→MainWindowVM;ShowMaintenanceCommandforwards the sameAppDataSourcestoMaintenanceWindow→MaintenanceWindowVM- Lookup services (
ExchangeLookupService,CurrencyLookupService, etc.) are instantiated inside ViewModel constructors from injected repositories — keepingApp.OnStartupclean and ViewModels free of repository construction logic - Design-time mock implementations for all repositories and lookup services live in
TD.AppInfra/DesignTime/for use by parameterless XAML designer constructors
- Introduce
TD.AppContractsto host shared application-service/lookup contracts (for exampleIExchangeLookupService,ISymbolLookupService) used by both WPF and future MAUI frontends - Add a MAUI frontend project (
OzzTradeDiary.MAUI) that reuses platform-agnostic core (TD), localization (TD.i18n), app infra (TD.AppInfra), and contract layers - Keep lookup/app-service contracts in
TD.AppContracts(separate from WPF-only assemblies) so both WPF and MAUI can share the same service abstractions - Remaining model repository classes in
OzzTradeDiary.SQLite - Functional data layer repositories and query logic
- Multi-market support: Stock, Forex, Crypto, Futures, Options, Commodities, and more
- Trade tracking with entry/exit orders, stop-loss, and take-profit levels
- Long and short trade directions
- Separate order type enums for entries and exits (EntryOrderType, ExitOrderType)
- Trade images with chart attachments and notes
- Multi-account and multi-exchange support
- Automatic SQLite database backup with ZIP archiving
- .NET 10.0 SDK
- Windows 10 (build 19041) or later
# Clone the repository
git clone https://github.com/your-username/OzzTradeDiary.git
cd OzzTradeDiary
# Build
dotnet build OzzTradeDiary.slnx
# Run
dotnet run --project OzzTradeDiary.NET/OzzTradeDiary.WPF/OzzTradeDiary.WPF.csprojView and ViewModel files use entity-first, verb-last naming (e.g., TradingAccountCreate.xaml, TradingAccountCreateVM.cs) so that files for the same entity sort together in Solution Explorer. Method names remain verb-first (e.g., CreateTradingAccount(), DeleteExchange()).
OzzTradeDiary.slnx
├── OzzTradeDiary.NET/
│ ├── OzzTradeDiary/ # Core models, shared helpers, validation (TD / TD.Extensions / TD.Helpers / TD.Validation) — platform-independent
│ │ ├── Models/ # Trade, TradeImage, Symbol, Exchange, Currency, Orders, etc.
│ │ ├── Extensions/ # Shared enum/text helpers reusable outside WPF
│ │ ├── Helpers/ # Shared query parameter contracts and other platform-agnostic helpers
│ │ └── Validation/ # Shared DataAnnotations-based validation (TD.Validation.ModelValidator)
│ ├── OzzTradeDiary.AppInfra/ # Shared MVVM infrastructure (TD.AppInfra namespace) — platform-independent base classes
│ │ ├── Commands/ # AbstractCommand and other shared command infrastructure
│ │ ├── DesignTime/ # Mock repositories and lookup services for XAML designer support (e.g. TradeMockRepository, CurrencyMockRepository)
│ │ ├── Services/ # Shared lookup services (generated, platform-agnostic — e.g. ExchangeLookupService, SymbolLookupService)
│ │ └── ViewModels/ # AbstractViewModel, AbstractDataErrorInfoVM, AbstractCreateEditVM, AbstractCollectionVM, AbstractDiaryVM, etc.
│ ├── OzzTradeDiary.i18n/ # Localization resources (TD.i18n namespace) — platform-independent, generated by OzzCodeGen/OzzGen
│ │ ├── *Strings.resx # Base resources (Action/Common/Error/Localized/Message)
│ │ └── *Strings.tr.resx # Turkish resources
│ ├── TD.RepositoryContracts/ # Shared repository contracts (TD.RepositoryContracts namespace) — platform-independent
│ ├── OzzTradeDiary.SQLite/ # Data access (TD.SQLite namespace) — platform-independent
│ │ ├── DbScripts/ # Generated SQL DDL scripts (one per model in OzzTradeDiary/Models)
│ │ ├── Extensions/ # SQLite-specific extension methods
│ │ ├── AbstractDatabaseRepository.cs
│ │ ├── MetadataRepository.cs
│ │ ├── CurrencyRepository.cs
│ │ ├── ExchangeRepository.cs
│ │ ├── TradingAccountRepository.cs
│ │ ├── SymbolRepository.cs
│ │ ├── TradeRepository.cs
│ │ └── ... # Repository classes live at the project root
│ ├── TD.Tools.SeedDemoData/ # Demo-data seeding console tool
│ └── OzzTradeDiary.WPF/ # Desktop UI (TD.WPF namespace) — Windows only
│ ├── Commands/ # WPF-specific command implementations
│ ├── Extensions/ # WPF-specific helpers
│ ├── Models/ # App settings, versioning, window positioning
│ ├── Resources/ # XAML styles, Bootstrap Icons
│ ├── Services/ # WPF-specific services (database backup, auto-backup); lookup services moved to TD.AppInfra
│ ├── ViewModels/ # WPF view models (inherit from TD.AppInfra base classes)
│ │ └── Maintenance/ # ViewModels for maintenance screens (TD.WPF.ViewModels.Maintenance)
│ └── Views/ # XAML views
│ └── Maintenance/ # Maintenance window and related views (TD.WPF.Views.Maintenance)
└── OzzCodeGen/ # Code generation settings
├── SqliteScriptsGen.settings # SQLite DDL generation config
├── ResourceGen.settings # Localization resource generation config
└── Vocabulary/ # English/Turkish translation files
Six-project MVVM architecture layered for platform portability:
| Project | Target | Role |
|---|---|---|
| OzzTradeDiary | net10.0 |
Core data models, shared helpers such as TD.Extensions.EnumExtension, shared query helpers in TD.Helpers, and shared validation utilities (for example TD.Validation.ModelValidator) with no platform dependencies |
| OzzTradeDiary.AppInfra | net10.0 |
Shared ViewModel, Command, MVVM infrastructure base classes, and generated lookup services (*LookupService) for reuse by WPF and future frontends (MAUI, web, etc.) |
| OzzTradeDiary.i18n | net10.0 |
Shared localization resources (*.resx/designer classes) generated from OzzCodeGen/OzzGen inputs |
| OzzTradeDiary.RepositoryContracts | net10.0 |
Shared repository contracts (interfaces) for data access abstractions |
| OzzTradeDiary.SQLite | net10.0 |
Data access layer — raw SQLite via Microsoft.Data.Sqlite, repository pattern |
| OzzTradeDiary.WPF | net10.0-windows10.0.19041.0 |
WPF desktop frontend — views, view models, commands, services |
Core models, localization resources, data access, and shared MVVM infrastructure are platform-independent, enabling future frontends (MAUI, web, etc.) to reuse them.
Model classes localize display metadata and validation messages through DataAnnotations that reference TD.i18n resource types.
Shared enum and text helper logic lives in TD.Extensions so UI projects such as WPF and future MAUI frontends can reuse the same behavior.
Shared ViewModel/Command base classes live in TD.AppInfra so both WPF and future platforms can inherit from a common, platform-agnostic foundation.
Exchange now includes navigation collections (Symbols, TradingAccounts) and Trade includes quantity fields (OrderQuantity, FilledQuantity) reflected across model, repository, and schema generation.
Trade also persists PlannedPositionValue, ExecutedPositionValue, PlannedEntryPrice, ExecutedEntryPrice, PlannedProfitLoss, RealizedProfitLoss, PlannedRiskAmount, and IsFullyClosed across model, repository mapping, and generated schema/indexes.
- Model names are singular; related table names are plural.
- Each model has a generated DDL file in
OzzTradeDiary.SQLite/DbScriptswith the same model name and.sqlsuffix. - Some models have generated seed files named
<PluralTableName>-Data.sqlinOzzTradeDiary.SQLite/DbScripts. - DDL and seed files are generated by
OzzCodeGen; do not edit manually. - Each repository CUD operation updates metadata timestamp via
SaveLastUpdateUtcAsyncinSqliteDatabaseMetadataRepository. MetadataRepositoryis shared via a singletonGetInstance()method; repositories use it internally and WPF ViewModels/services do not instantiate it directly.- When adding a generated seed file
<PluralTableName>-Data.sql, the corresponding repositoryInitializeDatabase()should callSqliteDbScriptInitializer.SeedIfEmpty(connection, "<PluralTableName>", "<PluralTableName>-Data.sql"). - Generated repositories can expose
OnLoadedpartial hooks for post-load behavior, especially when navigation properties are configured withAutoLoad=true. TradeRepositorymay use injected related repositories to populateTradenavigation collections duringOnLoaded.- Immutable repository keys:
Currency.CurrencyTickerExchange.ExchangeCodeSymbol.TickerFull
- Nullable text fields such as
Exchange.DefaultCurrencyshould be stored as SQLNULL, not the literal string"null". - Prefer
TD.SQLite.Extensions.SqliteExtensions.AddNullableParameter(...)for nullable SQLite parameters; avoidAddNullableTextParameter. - Use scaled
INTEGERstorage for value columns such asOrderValueandFilledValue, and useTEXTstorage for precision-sensitive price/quantity decimals.
At repository startup, initialization executes generated DDL scripts and applies baseline seed scripts only when target tables are empty.
- Seeding is idempotent and uses the inherited
SeedIfEmpty(...)helper fromAbstractDatabaseRepository. - Demo data for local debugging can be seeded with
TD.Tools.SeedDemoDataor the convenience launcherScripts/SeedDemoData.bat. SeedDemoDatagenerates demo symbols/trades/images for multiple crypto tickers with a crypto base-price dictionary for more realistic price generation.- Demo seeding creates two exchanges and two trading accounts, then distributes generated trades over a wider date range.
SeedTradessupports flexible account/exchange/day-range/suffix targeting for reusable seeding scenarios.Scripts/SeedDemoData.batis intended to reset the debug database before seeding so local demo runs are deterministic and clean.- Current generated seed scripts include:
OzzTradeDiary.SQLite/DbScripts/Currencies-Data.sqlOzzTradeDiary.SQLite/DbScripts/Exchanges-Data.sqlOzzTradeDiary.SQLite/DbScripts/Symbols-Data.sql
| Package | Version | Project |
|---|---|---|
| Microsoft.Data.Sqlite | 10.0.5 | OzzTradeDiary.SQLite, OzzTradeDiary.WPF |
SQLite DDL scripts and localization resources are generated by OzzCodeGen — a separate code generation tool. Configuration lives in OzzCodeGen/:
SqliteScriptsGen.settings— maps C# models to SQLite CREATE TABLE scripts inDbScripts/SqliteRepositoryGen.settings— generates SQLite repository classes and interfacesWpfMvVmCodeEngine.settings— generates WPF View, ViewModel, Command, and related MVVM base outputsCsModelClassCodeEngine.settings— usesCSharpModelClassCodeEngineas the root element for generated C# model class settingsResourceGen.settings— generates localization resources from vocabulary XML filesVocabulary/— bilingual term definitions (English/Turkish)LocalizedStrings.resxis sourced fromOzzTradeDiary.OzzGen- Model classes and database schema generation are sourced from
OzzTradeDiary.OzzGen(generator name:CS_Model_Class_Generator) QueryParametersclass generation is enabled for shared pagination/search contracts inTD.Helpers- Entity-specific query parameter generation (for example
TradeQueryParameters) is supported throughCsModelClassCodeEngine.settings - Searchable properties can be explicitly marked in generator settings so generated query contracts stay typed and aligned
- Generated model/validator code uses standardized header text for clearer generated-file context
- Generated repository interfaces are co-located inside repository class files (
I<Entity>Repository) - Generated repository hooks and auto-loading behavior depend on generator settings and execution order in
OzzTradeDiary.OzzGen - Generator execution order in
OzzTradeDiary.OzzGenshould be kept aligned with repository/schema dependencies and generated hook availability - Custom repository behavior should be added in companion partial files (for example
SymbolRepository.part.csorTradeRepository.part.cs) - Shared application/tool behavior may also be extracted into partial files and linked into multiple projects (for example
AppSettings.part.csfor debugSampleDatapath resolution)
Do not edit generated files manually (
DbScripts/*.sql, generated.resx, generated.Designer.cs, and generated repository/model/schema outputs) — they are overwritten on regeneration.