An open-source quantitative analysis platform for exploring financial markets through algorithmic lenses. The frontend employs a clean, modular architecture. It is built with Next.js, TypeScript, and Tailwind CSS.
QuantSandbox.io is a modern web platform that brings professional-grade quantitative analysis tools to anyone interested in exploring financial markets. By combining powerful algorithms with an intuitive interface, it makes quant analysis more accessible.
- 📊 Suite of Algorithms: Run the right algos, there's a plethora of them to choose from
- 📈 Real-time Data Processing: Up-to-date market data analysis
- 🎯 Interactive Visualizations: Clear, actionable insights through dynamic charts
- 📚 Historical Analysis: Backtesting; deep dives into historical market patterns
- Name: Bogdan Andrei
- Website: bgdnandrew.com
- X/ Twitter: @bgdnandrew
- Software Agency: Oriented Platforms
- Frontend (this repo): GitHub - QuantSandbox Frontend
- Backend Repo: GitHub - QuantSandbox
- Live Platform: quantsandbox.io
QuantSandbox was developed with inspiration from platforms such as Sentdex's pythonprogramming.net, and Quantopian's Quantopian Lectures (the Quantopian platform is now sunsetted, but the creator keeps its spirit alive through a nice newsletter).
From Wikipedia: Quantopian was a company that aimed to create a crowd-sourced hedge fund by letting freelance quantitative analysts develop, test, and use trading algorithms to buy and sell securities. In November 2020, Quantopian announced it would shut down after 9 years of operation.
Note on Documentation Style: Throughout this documentation, you'll notice the use of "we" instead of "I". While QuantSandbox v1.0.0 was developed solely by myself (Bogdan), this choice reflects the project's commitment to community and collaboration. Open source is about "we" - the collective power of developers learning and building together.
- Node.js 16.0.0 or higher
- npm or yarn
- Git
- Clone the repository:
git clone https://github.com/yourusername/quant-sandbox-frontend.git
cd quant-sandbox-frontend
- Install dependencies:
npm install
# or
yarn install
- Edit
.env.local
with your configuration. The Django backend should run on port 8000, if not confugured otherwise.
NEXT_PUBLIC_API_URL=http://localhost:8000
- Start the development server:
npm run dev
# or
yarn dev
The frontend application will be available at http://localhost:3000
.
# Development
npm run dev # Start development server
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run type-check # Run TypeScript compiler check
- Framework: Next.js 14 with App Router (React Server Components)
- Language: TypeScript
- Styling: Tailwind CSS
- State Management: React Hooks & Context
- API Communication: Custom API client with TypeScript
- Storage: Browser LocalStorage for analysis history (currently, as of v1.0.0, the app does not require user authentication)
UI LAYER (React Components)
↓ ↑
STATE MANAGEMENT
(React Hooks/Context)
↓ ↑
API FACADE
(src/lib/api)
↓ ↑
+----------------+----------------+
| | |
CorrelationService OtherService FutureService
(services/corr...) (services/...) (services/...)
| | |
+----------------+----------------+
↓ ↑
APIClient
(src/lib/api/client)
↓ ↑
BACKEND API
↓ ↑
DATABASE
We've implemented a layered architecture that emphasizes separation of concerns, type safety, and scalability. Here's why we made certain architectural choices:
// src/lib/api/services/correlation.ts
export class CorrelationService {
constructor(private client: APIClient) {}
async analyze(input: CorrelationInput): Promise<CorrelationResult> {
return this.client.post(ENDPOINTS.CORRELATION.ANALYZE, input);
}
}
Why This Pattern?
- Type Safety: Services enforce strict typing for inputs and outputs
- Encapsulation: Business logic is isolated from UI components
- Testability: Services can be easily mocked for testing
- Reusability: Services can be used across different components
// src/lib/api/index.ts
export const api = {
correlation: new CorrelationService(apiClient),
// Add new services here
};
Benefits:
- Single entry point for all API operations
- Consistent API access pattern across the application
- Easy addition of new services
- Centralized error handling
// src/lib/storage.ts
export const StorageManager = {
getHistory: (): StoredAnalysis[] => {
if (typeof window === "undefined") return [];
try {
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : [];
} catch (error) {
console.error("Failed to parse storage:", error);
return [];
}
},
// ... other methods
};
Key Features:
- The history of the algo runs is stored in localStorage, since the app in this version (v1.0.0) does not require user authentication
- Client-side persistence of analysis history
- Type-safe storage operations
- Error handling for storage operations
- Server-side rendering compatibility
Our components follow a clear hierarchy and responsibility pattern:
- Handle routing and layout
- Manage page-level state
- Coordinate between child components
Example: Correlation Analysis
// src/components/algorithms/correlation/CorrelationForm.tsx
export default function CorrelationForm({
onSubmit,
isLoading,
}: CorrelationFormProps) {
// Component logic
}
- Implement specific features or algorithms
- Maintain their own local state
- Communicate with parent through props and callbacks
- Reusable UI elements
- Consistent styling through Tailwind
- Accessibility-focused design
We use TypeScript extensively to ensure type safety:
// src/types/index.ts
export interface CorrelationInput {
ticker1: string;
ticker2: string;
start_date: string;
end_date: string;
}
export interface CorrelationResult {
correlation: number;
covariance: number;
// ... other fields
}
Our API client handles all HTTP communication:
// src/lib/api/client.ts
export class APIClient {
async post<T>(endpoint: string, data: any): Promise<T> {
// HTTP communication logic
}
}
We implement error handling at multiple levels:
- Service Level: Business logic errors
- API Client Level: Network and HTTP errors
- Component Level: UI-specific errors
- Storage Level: Persistence errors
We're planning to add more quantitative analysis algorithms:
-
Portfolio Optimization
- Mean-Variance Optimization
- Risk Parity Portfolios
- Black-Litterman Model
-
Risk Metrics
- Value at Risk (VaR)
- Expected Shortfall
- Stress Testing
-
Time Series Analysis
- ARIMA Models
- Kalman Filtering
- Regime Detection
-
Machine Learning Integration
- Factor Analysis
- Clustering
- Pattern Recognition
We welcome contributions to QuantSandbox! Whether you're fixing bugs, adding new features, or improving documentation, your help is appreciated.
-
Fork the Repository
# Clone your fork git clone https://github.com/bgdnandrew/quant-sandbox-frontend.git cd quantsandbox # Add upstream remote git remote add upstream https://github.com/bgdnandrew/quant-sandbox-frontend.git
-
Create a Branch
git checkout -b feature/your-feature-name # or git checkout -b fix/your-bugfix-name
-
Make Your Changes
- Write clean, documented code
- Follow our code style guidelines
- Add tests if applicable
-
Commit Your Changes
git commit -m "feat: add new correlation visualization" # or git commit -m "fix: correct date range validation"
-
Push and Create a Pull Request
git push origin feature/your-feature-name
// ✅ DO: Use clear, descriptive names
export interface CorrelationInput {
ticker1: string;
ticker2: string;
}
// ❌ DON'T: Use abbreviated or unclear names
export interface CorrInp {
t1: string;
t2: string;
}
// ✅ DO: Document complex functions
/**
* Analyzes correlation between two financial instruments
* @param input - Correlation parameters
* @returns Promise resolving to correlation results
*/
async function analyzeCorrelation(
input: CorrelationInput
): Promise<CorrelationResult> {
// Implementation
}
// ❌ DON'T: Leave complex functions undocumented
async function analyze(input: any): Promise<any> {
// Implementation
}
// ✅ DO: Organize components with clear structure
export default function AnalysisComponent() {
// 1. Hooks
const [data, setData] = useState(null);
// 2. Derived State
const isLoading = data === null;
// 3. Event Handlers
const handleSubmit = async () => {
// Implementation
};
// 4. Render
return (
// JSX
);
}
// ❌ DON'T: Mix concerns or have unclear organization
export default function MessyComponent() {
const handleClick = () => {};
const [data] = useState();
return <div onClick={handleClick}>{data}</div>;
const isLoading = !data;
}
// ✅ DO: Group related classes and use semantic naming
<div className="
flex items-center justify-between // Layout
p-4 rounded-lg // Spacing & Shape
bg-zinc-800 text-white // Colors
hover:bg-zinc-700 transition // Interactions
">
// ❌ DON'T: Use arbitrary values or mix concerns
<div className="p-[13px] bg-[#333] flex random-utility">
// ✅ DO: Write meaningful tests
describe("CorrelationForm", () => {
it("should validate input before submission", async () => {
const handleSubmit = jest.fn();
render(<CorrelationForm onSubmit={handleSubmit} />);
// Test implementation
});
});
// ❌ DON'T: Write implementation-dependent tests
describe("Component", () => {
it("should work", () => {
expect(true).toBe(true);
});
});
Note: Testing infrastructure is currently under development. We plan to implement:
-
Unit Testing
- Jest + React Testing Library (we're open to robust alternatives)
- Component testing
- Service layer testing
-
Integration Testing
- API integration tests
- End-to-end user flows
-
Performance Testing
- Load testing
- Component render performance
Contributors interested in helping set up the testing infrastructure are welcome!
-
Component Documentation
/** * CorrelationForm Component * * Collects and validates input for correlation analysis. * * @component * @example * ```tsx * <CorrelationForm * onSubmit={handleAnalysis} * isLoading={isAnalyzing} * /> * ``` */
-
Architecture Documentation
.development-docs
is a folder ignored by git, meant for unpolished documentation that is still evolving- Ideally, all the code should be intuitive, easy to read, and self-explaining
- Unfortunately, we do not live in an ideal world
- As the project matures, if the need arises, we should include a directory with the proper, polished documentation that we've gathered
We should always:
- Document architectural decisions
- Explain the reasoning behind patterns
-
PR Title Format
feat: add new visualization component fix: correct date validation docs: update architecture documentation style: improve component layout refactor: simplify correlation logic
-
PR Description Template
## Description Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Documentation update - [ ] Code style update - [ ] Refactor ## Testing Description of testing performed ## Screenshots If applicable
-
State Management
- Use local state for component-specific data
- Use context for shared state
- Keep state close to where it's used
-
Performance
- Use React.memo() for expensive renders
- Implement proper dependencies in useEffect
- Optimize re-renders
-
Error Handling
- Implement proper error boundaries
- Provide meaningful error messages
- Log errors appropriately
-
Accessibility
- Use semantic HTML
- Include ARIA labels
- Ensure keyboard navigation
-
Algo Suite Expansion
- Volatility Analysis Implementation
- Portfolio Optimization Tools
- Enhanced Data Visualization
- Supervised/ Unsupervised ML Features
- Other Algos
-
Technical Improvements
- Service Worker Implementation
- Improved Error Handling
- Performance Optimization
- Enhanced Type Safety
-
User Experience
- Responsive Design Improvements
- Enhanced Form Validation
- Interactive Tutorials
-
Advanced Features
- Real-time Market Data Integration
- Custom Algorithm Builder
- Advanced Portfolio Analytics
- Complex Machine Learning Integration
-
Infrastructure
- Caching Layer Implementation
- API Rate Limiting
- Performance Monitoring
- Automated Testing Pipeline
- Real-time Data Processing
- Distributed Computing Support
-
User Features
- User Accounts
- Saved Analysis History
- Custom Dashboards
- Analysis Sharing
- Community-contributed Algorithms
- Advanced Backtesting Framework
- Real-time Trading Integration
- Educational Resources
Special thanks to:
- Sentdex for inspiration and educational content
- Quantopian for their educational resources
- The open-source community for various tools and libraries
- Early users and contributors for valuable feedback
-
Django for Beginners by Will S. Vincent; IMHO this is the best Django resource for beginners out there; Will is regularly updating the website. Especially useful if your frontend contributions require knowledge of backend logic, for proper integration.
-
Python for Finance by Sentdex
-
Quantitative Economics with Python by QuantEcon
-
Awesome Quant on GitHub
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2024 Bogdan Andrei
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files...
For support, questions, or collaboration:
- 📧 Email: bogdan [at] orientedplatforms.com
- ✖️ X/ Twitter: @bgdnandrew
- 🌐 Website: bgdnandrew.com
Built with ❤️ by Bogdan Andrei and the open-source community.