Contributing to ExPostFacto

View Source

Thank you for your interest in contributing to ExPostFacto! This document provides guidelines and information for contributing to this Elixir backtesting library.

๐Ÿš€ Getting Started

Prerequisites

  • Elixir 1.12 or later
  • Erlang/OTP 24 or later
  • Git

Setting Up Your Development Environment

  1. Fork and clone the repository:

    git clone https://github.com/your-username/ex_post_facto.git
    cd ex_post_facto
    
  2. Install dependencies:

    mix deps.get
    
  3. Run the test suite to ensure everything works:

    mix test
    
  4. Check code formatting:

    mix format --check-formatted
    

๐Ÿ“‹ Development Guidelines

Code Formatting and Standards

Always run mix format after making any code changes. This ensures consistent formatting across the codebase using the standard Elixir formatter configuration defined in .formatter.exs.

Follow these Elixir best practices:

  • Documentation: Include proper @moduledoc and @doc attributes for all public modules and functions
  • Type Specifications: Use @spec type annotations for all public functions
  • Naming Conventions: Follow Elixir conventions (snake_case for functions/variables, PascalCase for modules)
  • Pattern Matching: Prefer pattern matching over conditional statements when possible
  • Error Handling: Use {:ok, result} and {:error, reason} tuples consistently
  • Function Design: Keep functions small and focused on a single responsibility
  • Data Flow: Use |> pipe operator for data transformations
  • Complex Operations: Use with statements for complex nested operations
  • Exception Functions: Use ! suffix for functions that raise exceptions (e.g., backtest!)

Code Quality Requirements

  1. No Compiler Warnings: Fix all compiler warnings when possible
  2. Test Coverage: Add comprehensive tests for new functionality
  3. Documentation: Include examples in documentation
  4. Type Safety: Add type specs for all public functions
  5. Performance: Consider performance implications for large datasets
  6. Backward Compatibility: Maintain backward compatibility when modifying public APIs

๐Ÿ—๏ธ Project Architecture

ExPostFacto is a backtesting library for trading strategies with the following core architecture:

Core Modules

Trading Strategy Framework

  • Supports pluggable strategies through module-function-arguments tuples {Module, :function, args}
  • Example strategies in ExPostFacto.ExampleStrategies
  • Strategy behaviour pattern for advanced state management

Trade Statistics Engine

The ExPostFacto.TradeStats namespace contains performance metrics calculations:

  • CompilePairs: Groups buy/sell actions into trade pairs
  • DrawDown: Calculates drawdown metrics
  • TotalProfitAndLoss: Computes P&L
  • WinRate: Computes win statistics
  • And more...

๐Ÿงช Testing Guidelines

Running Tests

# Run all tests
mix test

# Run specific test file
mix test test/ex_post_facto_test.exs

# Run tests with coverage
mix test --cover

Test Organization

Tests are organized to mirror the lib structure:

  • Unit tests for individual modules
  • Integration tests for end-to-end scenarios
  • Test helpers for generating mock data (CandleDataHelper)

Writing Good Tests

  1. Descriptive test names that explain what is being tested
  2. Arrange-Act-Assert pattern for test structure
  3. Mock data helpers for consistent test data
  4. Edge case testing (empty data, nil values, boundary conditions)
  5. Property-based testing where appropriate
  6. Integration tests with real market data when possible

๐Ÿ”ง Types of Contributions

๐Ÿ› Bug Reports

When reporting bugs, please include:

  1. Elixir and Erlang versions
  2. Minimal reproduction example
  3. Expected vs actual behavior
  4. Stack trace (if applicable)
  5. Data samples that cause the issue (anonymized if needed)

โœจ Feature Requests

For new features, please:

  1. Check existing issues to avoid duplicates
  2. Describe the use case and problem being solved
  3. Propose the API or interface design
  4. Consider backward compatibility
  5. Discuss performance implications

๐Ÿ“ Documentation Improvements

Documentation contributions are highly valued:

  • API documentation improvements
  • Tutorial and guide enhancements
  • Example strategies and use cases
  • Performance tips and best practices
  • Migration guides for breaking changes

๐Ÿš€ Code Contributions

Strategy Examples

New example strategies should:

  • Demonstrate specific trading concepts
  • Include comprehensive documentation
  • Have corresponding tests
  • Follow the established patterns

Example structure:

defmodule ExPostFacto.ExampleStrategies.MyStrategy do
  @moduledoc """
  A strategy that demonstrates [specific concept].

  ## Example

      {:ok, result} = ExPostFacto.backtest(
        data,
        {ExPostFacto.ExampleStrategies.MyStrategy, [param: value]}
      )
  """

  @doc """
  Strategy implementation with proper documentation.
  """
  @spec call(map(), ExPostFacto.Result.t(), keyword()) :: ExPostFacto.action()
  def call(data, result, opts \\ []) do
    # Implementation
  end
end

Technical Indicators

New indicators should:

  • Follow the existing indicator API patterns
  • Include mathematical documentation
  • Have comprehensive test coverage
  • Handle edge cases (insufficient data, etc.)

Performance Improvements

  • Profile before optimizing to identify actual bottlenecks
  • Benchmark changes to measure improvement
  • Consider memory usage alongside execution time
  • Maintain accuracy while improving performance

๐Ÿ”„ Development Workflow

1. Create a Feature Branch

git checkout -b feature/my-new-feature
# or
git checkout -b fix/bug-description

2. Make Your Changes

  • Write code following the guidelines above
  • Add or update tests
  • Update documentation
  • Run mix format to format code
  • Ensure tests pass with mix test

3. Commit Your Changes

Use descriptive commit messages:

git add .
git commit -m "Add RSI divergence detection strategy

- Implement bullish and bearish divergence detection
- Add comprehensive tests with edge cases
- Include usage examples in documentation"

4. Push and Create Pull Request

git push origin feature/my-new-feature

Then create a pull request with:

  • Clear description of changes
  • Link to related issues
  • Testing instructions
  • Breaking changes (if any)

๐Ÿ“‹ Pull Request Checklist

Before submitting a pull request, ensure:

  • [ ] Tests pass: mix test runs without failures
  • [ ] Code formatted: mix format has been run
  • [ ] No warnings: Code compiles without warnings
  • [ ] Documentation updated: For new features or API changes
  • [ ] Tests added: For new functionality
  • [ ] Backward compatibility: Maintained for public APIs
  • [ ] Performance considered: For changes affecting large datasets
  • [ ] Examples provided: For new strategies or features

๐ŸŽฏ Areas Needing Contribution

Based on TODOs and planned enhancements:

  1. Concurrent Statistics: Make trade statistics calculations concurrent
  2. Additional Metrics: More comprehensive backtesting metrics
  3. Strategy Framework: Expand strategy capabilities
  4. Performance Optimization: Memory and speed improvements
  5. Data Sources: Additional data input formats
  6. Visualization: Enhanced charting and reporting
  7. Risk Management: Position sizing and risk controls

๐Ÿค Community Guidelines

  • Be respectful and inclusive in all interactions
  • Help others learn and contribute
  • Ask questions when you need clarification
  • Share knowledge through documentation and examples
  • Follow the code of conduct (be kind and professional)

๐Ÿ“ž Getting Help

  • GitHub Issues: For bugs and feature requests
  • Discussions: For questions and general discussion
  • Documentation: Check existing docs first
  • Code Examples: Look at existing strategies and tests

๐Ÿท๏ธ Release Process

For maintainers:

  1. Update CHANGELOG.md with new features and fixes
  2. Bump version in mix.exs
  3. Run full test suite including integration tests
  4. Update documentation if needed
  5. Create git tag and push
  6. Publish to Hex with mix hex.publish

Thank you for contributing to ExPostFacto! Your contributions help make algorithmic trading more accessible to the Elixir community. ๐Ÿš€

โšก Quick Reference

# Essential commands
mix deps.get          # Install dependencies
mix test              # Run tests
mix format            # Format code
mix docs              # Generate documentation

Remember: Always run mix format before committing!