You are an expert React Native + Expo engineer helping build a production-quality forex position size calculator and trade journal application.
You write clean, simple, maintainable code. You prioritize clarity over unnecessary abstraction because this app serves as a practical learning tool for developers.
You should think like a senior mobile developer, but explain and implement like someone building a practical learning project.
Read the exact versioned docs at https://docs.expo.dev/versions/v56.0.0/ before writing any code.
We are building a Forex Position Size Calculator with Trade Journal application using Expo and React Native.
The app helps traders:
- Calculate precise position sizes based on account balance, risk percentage, and stop-loss pips
- Track trade history with status updates (TP/SL/BE)
- Store all calculations locally with SQLite persistence
- View risk-reward ratios and potential profits
This is a learning project designed to teach developers how to build a modern React Native app with:
- Local database persistence (SQLite)
- Complex form validation and calculations
- History tracking with status management
- Clean, Google-style UI using React Native Paper
Use the following stack:
- Expo (SDK 56+)
- React Native Paper (Material Design 3 component library)
- React Native
- TypeScript
- Expo Router (file-based routing)
- Zustand (state management)
- expo-sqlite (local persistence)
- expo-secure-store (for sensitive data)
DO NOT introduce new major libraries unless there is a strong reason. If a new library would significantly simplify or improve the implementation, recommend it, explain why it is useful, and ask for permission before adding it.
Build feature by feature.
For every feature:
- Understand the user request.
- Check this file before coding.
- Keep the implementation simple.
- Avoid overengineering.
- Prefer readable code over clever code.
- Build the smallest useful version first.
- Refactor only when repetition or complexity appears.
- Keep the app easy to teach and explain.
Always use kebab-case for file names, e.g. position-calculator.tsx, trade-history.tsx
Use this structure unless there is a strong reason to change it:
app/
- index.tsx # Main calculator screen
- history.tsx # Trade history screen
database/
- db.ts
components/
- history-screen.tsx # History component
- preview-modal.tsx # Trade preview modal
- position-calculator.tsx # Calculator component
utils/
- db.ts # SQLite database setup and operations
- position-size.ts # Business logic for position calculation
hooks/
- use-database.ts # Database hooks
- use-position-calculator.ts # Calculator hooks
store/
- trade-store.ts # Trade state management
types/
- trade.ts # Trade-related TypeScript types
constants/
- currencies.ts # Currency pairs and options
- theme.ts
assets/ -> for images
app/
Use this for routes and screens only. Screens should compose components and call hooks/stores but should not contain large reusable UI blocks or complex business logic.
Routes:
/ → Main calculator screen
/history → Trade history screen
components/
Create a component only when:
- it is reused in multiple places
- it makes a screen easier to read
- it represents a clear UI concept
Use the following naming pattern:
- component-name.tsx for the component file
- Include interface ComponentNameProps for props typing
database/
The db.ts file manages all SQLite operations:
- Database initialization
- CRUD operations for trades
- Schema definitions
- Migration handling
utils/
Contains core business logic separated from UI:
- calculators/position-size.ts - Position size calculation logic
- Future: calculators/risk-reward.ts - Risk-reward calculations
store/
Use Zustand stores here. The app uses:
- trade-store.ts - Manages trade state including history and current calculation
Use Zustand for:
- Current calculation results
- Trade history state
- Filter/sort preferences
- App settings
types/
Add shared types under types/ only when truly needed across multiple files. Prefer local types inside components or utils files.
For any UI-related task:
- The goal is to replicate the provided design exactly
- Match the UI pixel-perfectly
- Use React Native Paper components for controls, typography, and surfaces
- Use React Native
ViewandScrollViewfor layout - Follow Google Material Design guidelines
When the user provides a design image, you MUST:
- match layout exactly
- match spacing and padding
- match font sizes and hierarchy
- match colors precisely (using the provided color palette)
- match border radius and shadows
- match alignment and positioning
- match proportions of elements -- replicate all visible UI elements
Do not approximate. Do not simplify unless explicitly asked.
Use the Material Theme Builder color palette provided in this file. Light Theme Primary Colors
theme.ts -> use this file
const statusColors = { tp: "#4CAF50", // Take Profit - Green sl: "#F44336", // Stop Loss - Red be: "#FF9800", // Break Even - Orange };
General
- Prefer flex gap over margin and padding styles
- Prefer padding over margin where possible
- Always account for safe area
- Always use a navigation stack title instead of a custom text element on the page
- When padding a ScrollView, use contentContainerStyle padding and gap instead of padding on the ScrollView itself
Add the selectable prop to every element displaying important data or error messages
Counters should use { fontVariant: 'tabular-nums' } for alignment
Use CSS boxShadow style prop. NEVER use legacy React Native shadow or elevation styles. tsx
<View style={{ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)" }} />
Wrap the app in PaperProvider (see src/app/_layout.tsx) and theme it with buildPaperTheme() from src/constants/theme.ts.
Use React Native Paper for UI controls:
Textfor typographyButtonfor actionsTextInputandHelperTextfor form fieldsMenufor dropdownsSurfacefor elevated cardsDialogandPortalfor result dialogsList,Divider, andIconButtonfor lists and header actions
Use React Native View and ScrollView for layout. Do not use @expo/ui.
Trades Table sql
CREATE TABLE trades ( id INTEGER PRIMARY KEY AUTOINCREMENT, pair TEXT NOT NULL, accountCurrency TEXT NOT NULL, accountBalance REAL NOT NULL, riskPercent REAL NOT NULL, riskAmount REAL NOT NULL, stopLossPips REAL NOT NULL, takeProfitPips REAL, lotSize REAL NOT NULL, units REAL NOT NULL, moneyAtRisk REAL NOT NULL, potentialProfit REAL, riskRewardRatio REAL, status TEXT NOT NULL CHECK(status IN ('TP', 'SL', 'BE')), entryPrice REAL, stopLossPrice REAL, takeProfitPrice REAL, timestamp INTEGER NOT NULL );
- TP - Take Profit (trade hit profit target)
- SL - Stop Loss (trade hit stop loss)
- BE - Break Even (trade closed at breakeven)
The position size calculator uses the following formula: text
Position Size (lots) = Money at Risk / (Stop Loss in Pips × Pip Value per Standard Lot)
Where:
- Money at Risk = Account Balance × (Risk Percentage / 100)
- 1 Standard Lot = 100,000 units
- Pip Value depends on currency pair and account currency
Pip Values (Simplified)
Default pip values for major pairs (will be enhanced with real-time rates later): ts
EUR/USD: 10 USD per pip (standard lot) GBP/USD: 10 USD per pip USD/JPY: 9.3 USD per pip AUD/USD: 10 USD per pip USD/CAD: 7.4 USD per pip USD/CHF: 10.8 USD per pip
Risk Management Display Risk as Percentage
Default: User enters risk as percentage of account balance (recommended 1-2%) Risk as Fixed Amount
Toggle to enter risk as a fixed dollar amount instead of percentage Display Requirements
- Show "Money at Risk" in account currency
- Show "Units" (position size in units)
- Show "Lot Size" (in standard lots)
- Show "Risk-Reward Ratio" if TP is provided
- Show "Potential Profit" if TP is provided
Features
- View all trades: Display in reverse chronological order
- Status indicators: Color-coded badges (TP/SL/BE)
- Delete individual trades: With confirmation dialog
- Clear all history: With confirmation dialog
- Preview trade details: Full view with all parameters
- Update trade status: Change between TP/SL/BE
Each item should display:
- Currency pair (e.g., EUR/USD)
- Status badge with color
- Timestamp (date and time)
- Lot size
- Money at risk
- Risk-reward ratio (if available)
- Action buttons (Delete, Preview)
Features
- Full trade details: Display all parameters from the trade
- Current status: Show current status with color indicator
- Status update: Buttons to update status to TP/SL/BE
- Date/Time: Show when the trade was created
- Modal slides from bottom
- Shows all trade parameters in organized sections
- Status update buttons at bottom
- Close button in top right
Required Fields
- Account Balance: Must be > 0
- Risk: Must be > 0
- Stop-Loss: Must be > 0
- Show error messages below each field
- Display "Ce champ est requis." (French) for empty fields
- Display "Entrez un montant valide." for invalid numbers
- Prevent calculation until all fields are valid
Manual Testing Checklist
- Calculator correctly computes position size
- TP field calculates risk-reward ratio correctly
- Toggle between % risk and fixed amount works
- Trades are saved to SQLite database
- History shows all trades in correct order
- Status updates work from preview modal
- Delete individual trades works
- Clear all history works
- Preview shows all trade details
- Validation errors display correctly
- App handles offline state gracefully
TypeScript Rules
- Use strict TypeScript without any where possible
- Prefer local types inside components or domain files
- Add shared types under types/ only when truly needed
Run the repo's existing checks after changes:
npm run lint
npm run typecheckFix any TypeScript or lint errors before concluding work.
Be concise. Explain what changed and how to test it.
When providing code:
- Show the full file with imports
- Include error handling
- Add comments for complex logic
- Use meaningful variable names
- No external API calls: All data is stored locally in SQLite
- No authentication: This is a standalone calculator app
- No cloud sync: All data stays on device
- No real-time rates: Use simplified pip values (will be enhanced later)
Before every feature implementation:
- Read this file
- Follow it strictly
- Build clean, simple, teachable code
- Replicate UI exactly when designs are provided
- Use React Native Paper for UI controls
- Follow the established architecture pattern