stardance has been extended another month! the new deadline is october 31 :)

You are browsing as a guest. Sign up (or log in) to start making projects!

igowu

@igowu

Joined June 5th, 2026

  • 9Devlogs
  • 2Projects
  • 2Ships
  • 33Votes
Open comments for this post

2h 39m 52s logged

Puppy - FRC 5113


What is it?

Puppy is a robot designed for the REBUILT FRC 2026 game. It is our team’s outreach bot, meaning that it will be used to attract new members into our team during special events.


Framework & design

The biggest problem when starting this is that the deprecated RoboRIO cannot use the modern robot frameworks (used to control the robot at a high-level). The roboRIO is incompatible with the new frameworks because they are tightly coupled to the newer hardware.

To overcome this, I created a new framework that mimics the behavior of the current modern frameworks. It subclasses TimedRobot, allowing for each robot mode to be encapsulated in its own module rather than all lifecycle hooks needing to be in the same class. In other words, this eliminates the problem of a gigantic robot.py file that orchestrates the entire codebase.

Here’s a diagram to show how each mode is separated:

Robot Framework (inherits from `TimedRobot`)
    │
    ├── DisabledMode
    ├── AutonomousMode
    ├── TeleopMode
    └── TestMode

Testing

Unit testing robot runtime behavior isn’t feasible. Therefore, I created integration tests to ensure the correct behavior of the lifecycle methods in each mode (i.e. entered, periodic, exited).


Robot Code

I completed the drivetrain subsystem as a model for the rest of the subsystems to follow. The file structure encapsulates each of the subsystems, making it impossible for other subsystems to talk with or command the hardware of any others. For example:

drivetrain/
├── io/
│   ├── base_io.py
│   ├── real_io.py
│   └── sim_io.py
├── constants.py
├── drivetrain.py
└── controller.py

**Note: The image is of our competition bot that we’re going to use for an upcoming offseason event - I couldn’t find one of Puppy. I’ll post one next week!


2
0
46
Ship

Contango

I built a Python framework for quantitative research of trading strategies, whether it be backtesting them, tuning parameter combinations, or turning the results into graphs that can easily reveal profitability/risk in strategies. It started as solely a backtesting framework, but it has grown into an entire suite for optimization and analysis. The latest release, v0.1.1, is now on PyPI.

What it is

It is an event-driven trading framework with two ways to build strategies. Strategy gives you complete control over the framework, while RuleBasedStrategy provides a higher-level interface for expressing trading rules with less boilerplate. On top of that is the research tooling. Contango can run Cartesian parameter sweeps, evaluating every combination of selected parameters rather than forcing you to manually run a strategy over and over. That makes it possible to take a strategy idea and view a whole parameter space in one run.

Market data is handled through a local repository that caches OHLCV data, so repeated experiments don’t need to keep downloading the same data. This permits for offline usage once data has previously been downloaded. Yfinance (a data provider) works without setup or an API key, while the data provider system is designed so additional providers can be added without touching codebase’s internals. Possibly the most important part is the graphs. Equity curves, drawdowns, trade-quality metrics, parameter distributions, risk/return views, and more can be generated from the results of a research run. However, the goal isn’t just to analyze the amount of profit the strategy returns. Instead, it’s to make the behavior of the strategy visible by exposing a variety of different risk/trading/drawdown metrics, revealed clearly in the generated graphs.

What was hard

I spent a lot of time separating components, defining cleaner interfaces (modularity), and deciding where abstraction was beneficial rather than just adding redundancy and boilerplate. The parameter optimization system was another massive difficulty to create. A Cartesian sweep sounds simple on paper; however, the question arises: how do you distinguish all of the strategies from each other? My initial solution was to display all of the parameters for each strategy, but this ended up with strategy names that were way too large to render. Lastly, documentation ended up being much more work than I expected. I wanted someone to be able to use Contango without having to understand how its internals work first, while still having enough documentation available for someone who actually wants to extend the framework.

What I’m proud of

The part I’m happiest with is that Contango now feels genuinely easy to use after a small learning curve. You can write a strategy, point it at market data, sweep its parameters, and get a collection of research results and visualizations without having to manually glue all of those pieces together. The other thing I’m proud of is the amount of attention that I put into making the project understandable. The public API is documented, the internal API is documented, components have been modularized, and there are now unit tests for essentially everything that needs them. It’s not finished in the sense that no software ever is, but it finally feels complete.

How to test it

Install it from PyPI:

pip install contango

Then run the included research demo:

python -m contango.research.demo_strategies.cartesian_bollinger_strategy.runner

The demo runs a Bollinger Band strategy across a Cartesian grid of parameters and generates performance and parameter-analysis graphs (HTML) that can be reviewed.


I want to thank Stardance for this experience - the opportunity to build software while earning rewards and be in such a welcoming community is amazing to me. I’m looking forward to future work with Hackclub!

  • 7 devlogs
  • 58h
  • 19.01x multiplier
  • 1046 Stardust
Try project → See source code →
Open comments for this post

6h 56m 5s logged

Contango - Devlog #8 (final devlog?)


The latest version of Contango (v. 0.1.1) been is released on PyPI.

What Changed?

Rule-based strategies and Cartesian Sweeps

Strategies can be created using a rule-based system that allows them to be swept over all combinations in a Cartesian Search. This is especially useful for finding a broad spectrum of tuned parameters after creating & coding a strategy concept.

Documentation

The documentation has been expanded to give direct tutorials on how to set up strategies and make additions to the framework without touching any of its internals. Further, the documentation now has in-depth explanations on the public AND private API.

Other

  • The graphs now have a GraphType subclass - essentially, graphs can now be added to or removed by the user if this is desired. This eliminates the hardcoding and confusing behavior that the graphs had prior to this change.
  • Unit tests created for just about everything that needs it.
  • General maturing of the framework, whether that be creating modular components, exposing or hiding certain details from the user, or creating docstrings for the public and private API.

That’s all. This will likely be my last devlog before shipping for the final time. I’m praying to the Gods of Stardance that I can get a 3d printer! We’ll see.

0
0
82
Open comments for this post

6h 39m 42s logged

Contango - Devlog #7


Research

Research has been rough. I haven’t found any real edge with a
calmar ratio above 1.0, nor a sharpe ratio that is statistically meaningful to suggest a somewhat profitable strategy.


Cartesian Parameterized Grid Search

This system was absolutely effective in what it did; however, I’ve concluded that using brute-force to generate strategies does not yield any
genuine edge. The system was powerful, but honestly hard to use; hence, I came to the decision of deleting it as it did not have much use other than
brute-forcing trading strategies.


Rule-based Strategies

Rule-based strategies, again, allow for strategies to be created with minimal and highly declarative code. The API has improved significantly
with less unnecessary generics and more docstrings. It will be the intended system for backtesting strategies rather than using static strategies. They will both coexist, however; the static strategies will be intended to be used for live trading if implemented in the future.


Graphs

The graph system was relatively ad-hoc, hard to use, and hardcoded; therefore, I have restructured it to take a more composable approach to
allow for the user to create & add graphs. The default graphs have not disappeared; however, they can be overridden. New graphs can be subclassed and the user can register & create custom graphs if desirable.


Future

  • Finish the graphing system.
  • Fix all of the demo strategies for the new structure.
  • Create new unit tests for the codebase.
  • Publish to PyPI and commit to github.

I’m beginning to wrap up the project to get it to a publishable state.

0
0
33
Open comments for this post

6h 35m 50s logged

I was wrong.

…But that’s okay.


Hyper-parameterized Cartesian grid search

I built a system capable of searching an enormous strategy space, and the system worked. My original goal was to have computers literally generate trading strategies and hypothesize by themselves through testing all possible indicator combinations. However, simple strategies based on widely known indicators aren’t producing the profitability I was initially looking for.


However, this isn’t necessarily bad news - it just means that the system should be used to help hypothesizing rather than automating it entirely. The same system can be used heavily for optimization of a concept. For example, it can completely automate the process of testing if ATR scaling or an RSI confirmation yields better results. Further, I can still find optimal parameters through the grid search for a given strategy.


On Overfitting

A grid search inherently will find “amazing” results - however, that doesn’t necessarily mean that it would actually perform well in the market. The parallel coordinate graphs, heatmap graphs, and manual walk-forward tests have made it genuinely easy to pick out overfit results, so this accepts part of my hypothesis in the earlier devlogs.


Future

I finished most of the work I wanted to do. I stress tested the suite, created unit tests, and created the hyper-parameterization system in its entirety. Now is finally the fun part - research. I’m genuinely curious if I’m able to find some profitable strategies with my system, so my future devlogs will likely be related to the research I’m going to conduct.


That’s all. Have a great day!

0
0
10
Open comments for this post

13h 2m 25s logged

Devlog #5 - Contango


Hyperparameter Cartesian grid search

Apparently this isn’t easy to design! Who could have thought? Not me!

Jokes aside, this has been a miserable experience. I’ve created two different designs so far. The first one failed outright - far in, I realized that having mutable objects in a nested grid search breaks all of the results, and it wasn’t easy to integrate Callable types with what I had already created, so I scrapped it.

Another massive hurdle was trying to find out how to parameterize the rules that indicators must follow (i.e. close crosses above middle bollinger band crosses). The idea here is to have a set of rules, and have each and every one of them parameterized amongst each other to find the best rules in the subset.

My current design uses callables to generate fresh instances of both the parameters and indicators used in the hyperparameter grid search.

However, another issue has become known to me - how do you derive unique, dynamically created names for each individual parameterized result? My thought is to derive the name of the indicators from the caller (which I have been doing), but on top of that, force all rule-based modules in my codebase to implement an ABC & override repr. This has not been formally implemented yet.


Future

  • Finish & finalize the hyperparameter Cartesian grid search strategy.
  • Create unit tests for it.
  • Genuinely take some time to look over the codebase, see what may be confusing for any users, & implement fixes for them (whether it be documentation, simplifying concepts, or creating abstractions for modules).
  • Add quite a lot of documentation.
  • Ship.

0
0
11
Open comments for this post

6h 52m 16s logged

Devlog #4 - Contango


Rule-based Strategies

I found a lot of issues and limitations with them. However, after working for hours coding them, I believe I’ve reached a point where I’m happy with how they’re looking.

To summarize, every strategy is composed of rules, where a rule has a condition & action. If the condition is true, the action (intent) is released. In the case of this suite, intents express to buy, sell, create stoploss orders, etc. You can see the syntax in the attached screenshot.


Unit testing

Unit tests are completely finished! The suite has 290 passing unit tests as of now.


Parameterization

I’m going to give parameterization another try. Instead of creating another layer on rule-based strategies, I’m going to instead pass indicators (or “streams” as I call them) into a base strategy along with their parameters in an attempt to perform a Cartisan hyperparameter grid search for both the indicators and their parameters. That was a mouthful to say; however, I’ll demonstrate what I mean in the next devlog (hopefully).


Future

As always, I like to document what I want to accomplish before shipping:

  • Start & finish the Cartisan hyperparameter grid search API, along with testing it.
  • Fix up documentation (there are major gaps at this point in my development from alpha v.0.1.0).
  • Release on PyPI.

That’s it. Happy coding!


0
0
6
Open comments for this post

7h 58m 44s logged

Devlog #3 - Contango


Rule-based Strategies

I completed the rule-based strategy engine, and it seems to be yielding correct results with integration tests. It allows for both Cartesian Parameterization & indicator parameterization, mentioned in the previous devlog.


Unit tests

I’ve noticed that as I make more changes, my unit tests have been lacking. The majority of the time for this devlog has been spent creating unit tests for my code. This has proved to be very time consuming and tedious (it always is), and has taken more than five hours at this point. However, I’m only halfway done, so this might take a while longer…


Future

I always like to make a list for what I want to do before shipping. Here’s where I’m at now:

  • Finish unit tests & fix any issues they reveal
  • Manually test everything myself by creating example strategies
  • Document everything (at this point there are massive gaps in documentation from the changes I have made)
  • Release v.0.1.1 on PyPI & then ship

That’s all. Have a great rest of your day!

0
0
6
Open comments for this post

10h 7m logged

Devlog #2 - Contango

Massive changes have been made relating to strategy creation & the capability of the framework.

Creating a strategy

An entire Bollinger Band Mean Reversion strategy now looks like this:

indicators = {"bb": BollingerBands(period=period, k=num_std)}

rules: Sequence[Rule[TradingContext, Intent]] = [
    Rule(
        Predicate(lambda ctx: ctx.event.close < ctx.indicators["bb"].value.lower),
        Emit(EnterLongIntent(symbol=symbol))
    ),
    Rule(
        Predicate(lambda ctx: ctx.event.close > ctx.indicators["bb"].value.upper),
        Emit(ExitIntent(symbol=symbol)),
    )
]
super().__init__(
    indicators=indicators,
    rules=rules,
    position_sizer=AllocationPositionSizer(size)
)

With this structure, an entire trading strategy can be expressed with a few unequivocal rules.

Further, because indicators and their parameters are major components, both can now be parameterized during optimization. That means grid searches can iterate over not only different parameter values, but entirely different indicator combinations.

In a favorable environment, this means that with enough computing power, you can automate the creation and development of strategies. However, in practice, real markets make this significantly less straightforward due to overfitting; therefore, human analysis is still essential since larger search spaces dramatically increase the risk of these biases. Nonetheless, this gives a major advantage to manually creating code for each strategy individually.

Other things

  • I restructured the file tree to make the codebase easier for new future contributors (including myself) to make changes.
  • I created a rule system for the backtester under the hood that doesn’t hard-code any limitations in preparation for full support of pyramiding, multiple tickers, & short selling.

Future

There are some things I want to do before shipping. I’ll list them here:

  • Complete the indicator grid search mentioned above.
  • Stress-test everything & create unit tests where necessary.
  • Complete the documentation - especially with strategy creation, which is not definitely extensive enough as of now.

Anyway, enough technical talk for this devlog - happy coding!

0
0
10
Ship

Contango

Have you ever wanted to create strategies programmatically for the stock market, cryptocurrencies, or anything else related to trading?! Maybe not… But I have!

So, what is Contango?

Contango is a full trading engine that allows you to make strategies in Python without worrying about any potential biases in your workflow. Instead of focusing on simulation, metrics, results, and graphs, you can avert your focus solely to the quality of the strategies you create.

Strategies - what do they look like?

Strategies are a part of an event-driven engine. This means that they receive and react to events that are released from a “mode”. A “mode” is anything that handles the logic of the event bus and/or engine - backtesting, live trading, etc. An example of a strategy:

class MyStrategy(Strategy):
    """
    A very simple strategy outline - not all logic is included.
    """
    def on_market_event(self, event: MarketDataEvent) -> None:
        # Strategy market logic here

    def on_end(self) -> None:
        ...

Results

Contango processes the raw events emitted from your strategy and converts them to metrics. These metrics are then used to produce seven unique graphs. Each of these graphs tell you something unique about the strategy, whether it be profitability, risk, drawdown, consistency, win rate, etc. For most modern workflows, this is enough; however, all modules are cleanly decoupled from each other, so raw events or raw metrics can be processed & analyzed however you would like.

Challenges

Challenges:

  • A massive learning curve. I’ve spent probably 50 hours or more just researching and absorbing the information used in this project.
  • Packaging was difficult to get right, whether it be “missing type stub” warnings or incorrect rendering of my README.md.
  • Documentation was terrible to write. Spending large amounts of time writing English words instead of code that accomplishes something was extremely tedious, yet completely necessary for a shipped project like this.

I’m proud of this project

Genuinely, this is one of the first big project I’ve ever made. I have never released anything to PyPI, nor shipped something of this scale before.

Hackatime only shows 22 hours since I set it up partway through, but Contango’s been my main project since June, and it’s the second largest thing I’ve built.

Usage

The GitHub has detailed instructions, demos, videos, and more; however, since it’s so short, here is how to install the project & run the built-in demo from any python IDE:

pip install contango
python -m contango.research.research_strategies.bollinger_band_mean_reversion.runner

Final Notes

I’ve had a lot of fun with this project, and I hope anyone who sees this enjoys it just as much as me. Happy coding!

  • 1 devlog
  • 25h
  • 6.10x multiplier
  • 61 Stardust
Try project → See source code →
Open comments for this post

24h 32m 25s logged

Devlog #1 - Contango

I have finally released Contango on PyPI!

What is Contango?

Contango is a full trading engine that helps you build trading strategies. It does all of the heavy lifting - the results, metrics, and the entire trading engine behind the hood.

I’ve never created a package on PyPI, so doing this was a massive learning experience - from uploading to TestPyPI to iterating multiple times before I got my pyproject.toml right.

I sent one of the graphs generated after testing my project demo out using the package.

See the package on PyPI here: https://pypi.org/project/contango/

Have a great rest of your day!

7
0
38

Followers

Loading…