Private strategies
You don't have to publish a strategy to run it. The repo is laid out so you can drop a private strategy into your local clone, build, and run -- without forking, without managing a second repo, and without leaking it to upstream.
The convention
strategies/
├── noop/ ← committed, public
├── <community_strategy>/ ← committed, public
└── private/ ← gitignored as a directory
├── my_basis/ ← private, never pushed
└── my_market_maker/
.gitignore excludes /strategies/private/ as a whole directory. Anything you put under it is invisible to git.
Enabling private strategies in your build
Permafrost ships two binaries -- the daemon (permafrostd) and the CLI (permafrost) -- and a strategy must be linked into both to be both runnable and backtest-able. Each binary has a symmetric pair of files:
| File | Tracking | Purpose |
|---|---|---|
cmd/permafrostd/strategies.go | committed | Community / reference strategies for the daemon |
cmd/permafrostd/strategies_local.go | gitignored | Your private strategies for the daemon |
cmd/permafrost/strategies.go | committed | Same set, for the CLI (strategy backtest, strategy list) |
cmd/permafrost/strategies_local.go | gitignored | Same set, for the CLI |
Example local file (you maintain a copy in both cmd/permafrostd/ and cmd/permafrost/):
package main
import (
_ "github.com/teslashibe/permafrost/strategies/private/my_basis"
_ "github.com/teslashibe/permafrost/strategies/private/my_market_maker"
)
Both files compile into their respective binaries; the registry sees both sets at startup. Build:
go build -o bin/permafrostd ./cmd/permafrostd
go build -o bin/permafrost ./cmd/permafrost
To run an OSS-only build (no private strategies), delete both strategies_local.go files. To remove a single private strategy from a build, delete its line in both files.
Backups (you have to think about this)
Anything under strategies/private/ is gitignored. That means it isn't backed up by your normal git push flow. Three failure modes to plan for:
git clean -fdxwipes untracked files. You will eventually run this command and forget what's instrategies/private/.rm -rfmistakes. Standard.- Disk failure. Standard.
Pick at least one mitigation:
- Time Machine / Backblaze / equivalent. Easiest. Make sure
strategies/private/is not in your backup-exclude list. - Periodic tarball.
tar -czf ~/backup/strategies-$(date +%F).tar.gz strategies/private/in a cron / launchd job. - Private fork on a separate branch. Maintain a
privatebranch in your own fork that includesstrategies/private/andcmd/permafrostd/strategies_local.go. Push to that branch only. Never tomain. Most invasive but gives you full git history.
For trading code, plan at least two of the above. Strategies that lose money are sad; strategies that lose themselves are worse.
Avoiding accidental leaks
Three failure modes:
-
git add -f-- bypasses.gitignore. Easy to do by accident with a wildcard. A pre-commit hook is good insurance:.git/hooks/pre-commit#!/bin/shif git diff --cached --name-only | grep -E '^(strategies/private/|cmd/permafrostd/strategies_local\.go$)' > /dev/null; thenecho "ERROR: refusing to commit private strategy paths"git diff --cached --name-only | grep -E '^(strategies/private/|cmd/permafrostd/strategies_local\.go$)'exit 1fi -
IDE auto-stage. Some setups stage all changes. Check yours.
-
Branch pushes. A branch that includes a stash apply may carry private files.
git statusbefore every push.
The agent run foreground iteration command lives on the CLI binary; the daemon permafrostd is the production-grade supervisor. Both need the same set of strategy registrations -- that's why the four-file pattern exists. If you only ever run the daemon, you can skip the two cmd/permafrost/strategies*.go files, but strategy backtest will then refuse to load your private strategy by name.
Sharing a private strategy across machines
If you run permafrostd on more than one machine (laptop + server), you'll want to sync. Options in increasing rigor:
- scp / rsync. Two commands. Drift-prone.
- Private Git repo for
strategies/private/only. Initialize a separate repo insidestrategies/private/, push it to a private remote. The outer repo's.gitignorekeeps it out of public push. - Private fork. As above in the backup section. One repo, two branches:
main(clean OSS, syncs upstream) andprivate(your build, never pushed to upstream).
Promoting a private strategy to public
When you decide a strategy is good enough to share:
mv strategies/private/my_strategy strategies/my_strategy
# remove the import line from strategies_local.go and add it to strategies.go
git add strategies/my_strategy/ cmd/permafrostd/strategies.go cmd/permafrostd/strategies_local.go
git commit -m "Promote my_strategy to public"
Open a PR upstream if you want others to use it. The framework doesn't care either way.