Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building an Automated Trading System with Symfony

Building an Automated Trading System with Symfony

Avatar for Jonathan H. Wage

Jonathan H. Wage

June 12, 2025
Tweet

More Decks by Jonathan H. Wage

Other Decks in Technology

Transcript

  1. 1

  2. Who am I? Jonathan H. Wage CEO & Founder of

    TradersPost • Married to Megan Wage • Living in Grand Rapids, Michigan • Using PHP 20+ years • Doctrine and Symfony contributor from time to time • Now I am building trading automation software at TradersPost Baby Weavers and Wages
  3. Who uses TradersPost? • Traders & Investors (B2C) • Trading

    Communities (B2B) • Strategy Developers
  4. Monitoring Messenger Get the code: https://gist.github.com/jwage/d1bfcfbdbfd44aa73d 285f2fa47e65a9 Queue wait time

    for our most important queues should be less than 100ms Adds queueWaitTime value to every message that is handled and is sent to logs and NewRelic for monitoring.
  5. Lower Messenger Sleep By default the --sleep option is set

    to 1 second. Set it to something lower to keep the queueWaitTime as low as possible when load is low and workers are waiting for new messages to handle
  6. Supervisord Use Supervisord to ensure your messenger worker processes are

    always running! Live trade execution workers: - 3 servers - 50 worker processes per server - This means 150 queue connections required for live execution
  7. Sponsoring Messenger Improvements 1. [Messenger] implementation of messenger:consume, which processes

    messages concurrently #53964 https://github.com/symfony/symfony/pull/53964 2. RabbitMQ implementation that doesn’t use polling…get queueWaitTime closer to 0ms. Hiring Robin and baksla.sh to help with this!
  8. Automated Testing Keeping our software stable with a large suite

    of automated tests and static analysis checks
  9. Automated Testing Using automated testing and static analysis tools are

    a must! • phpunit/phpunit • symfony/panther • zenstruck/browser • vimeo/psalm • squizlabs/php_codesniffer • doctrine/coding-standard
  10. Run Psalm On Max Pain Mode Why? We don’t ever

    want runtime bugs caused by invalid types, unknown method names, etc. Eliminates entire categories of bugs from being possible. Refactor and ship with high confidence.
  11. Live Component Polling Poll live components for updates while a

    trade is in progress and stop as soon as it is done executing.
  12. Managing Stimulus Controller State Get the code: https://gist.github.com/jwage/5b42c0034321cfbd896ca9acbbad4304 Added new

    lifecycle callbacks to stimulus controllers whenever a live component or turbo morphs the element a stimulus controller is attached to so you can manage state.
  13. Rerender Live Component On Visibility Change Opt-in live components to

    re render themselves when they become visible or focused.
  14. Symfony Local Server With Multiple Domains Important to start server

    with --allow-cors Thanks to Hugo Alliaume! https://github.com/symfony-cli/symfony-cli/pull/293
  15. PGBouncer + PgSQL PGBouncer is a lightweight connection pooler for

    PostgresSQL. Using PGBouncer with PgSQL can significantly increase the number of clients that can connect to your database
  16. PGBouncer + PgSQL PGBouncer is a lightweight connection pooler for

    PostgresSQL. Using PGBouncer with PgSQL can significantly increase the number of clients that can connect to your database
  17. PGBouncer + PgSQL PGBouncer is a lightweight connection pooler for

    PostgresSQL. Using PGBouncer with PgSQL can significantly increase the number of clients that can connect to your database Session Pooling: Assigns a server connection to a client for the entire session. Supports all PostgreSQL features.
  18. PGBouncer + PgSQL PGBouncer is a lightweight connection pooler for

    PostgresSQL. Using PGBouncer with PgSQL can significantly increase the number of clients that can connect to your database Transaction Pooling: Assigns a server connection only for the duration of a transaction. Some session-based features won’t work.
  19. PGBouncer + PgSQL PGBouncer is a lightweight connection pooler for

    PostgresSQL. Using PGBouncer with PgSQL can significantly increase the number of clients that can connect to your database Statement Pooling: Most aggressive method. This is transaction pooling with a twist: Multi-statement transactions are disallowed.
  20. PgSQL + PGBouncer + Doctrine To use PGBouncer with Doctrine

    you must turn on prepared statement emulation.
  21. Doctrine ORM Encrypted Values Built with defuse/php-encryption • Keys are

    stored in PostgreSQL, encrypted at rest. • Each customer's tokens are encrypted using derived per-customer keys. • Keys are derived from a master key and customer-specific UUIDs. • Keys are automatically rotated — re-encryption happens seamlessly. • Encryption and decryption are fully automated via Doctrine custom types. • Sensitive fields are transparently encrypted/decrypted on persist and hydrate. • No plaintext tokens are ever written to disk or logs.