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

igowu

@igowu

Joined June 5th, 2026

  • 7Devlogs
  • 1Projects
  • 1Ships
  • 15Votes
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
32
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
8
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
10
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
8
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
36

Followers

Loading…