Skip to content
v3 redesign is live — welcome to the trading cockpit.
Market updates, stock news, and futures insights — 3x/week, freeSubscribe free
Skip to content
build.logtraders.online=2,166trades.60s=74swings.ranked=308edge.latency_ms=42ms
// educational content · not financial advice

Everything on this page is published for educational and informational purposes only. Nothing here is investment, financial, legal, tax, or trading advice, a recommendation to buy or sell any security or contract, or a solicitation of any kind. Trading futures, options, equities, and crypto involves substantial risk of loss and is not suitable for every investor. Past performance — including any backtests, demos, or examples shown — does not guarantee future results. Consult a licensed professional before acting on anything you read here.

// module · coding fundamentals

Code, terminal, Git. The floor every automator stands on.

Trading automation tutorials skip the boring stuff: which language, which shell, which Git command. This module starts at zero and gets you to a working environment, a clean commit, and the eight failure modes you will absolutely hit. No paywall, no upsell, no login.

languages compared
4
terminal commands
50
git workflow steps
10
failure scenarios
8
// 01 · languages

Four languages. One task. The same five concepts.

Every automation language hits the same five concepts: variable, conditional, broker call, position size, logging. Once you see the pattern in one, the rest are just different syntax for the same shape.

// language primer

One task. Four languages. Same five concepts.

Buy when RSI < 30, exit when RSI > 70. Compare the syntax — then read the bottom table to confirm the concepts are the same in all four.

// python — rsi_strategy.py
import logging
from alpaca.trading.client import TradingClient
from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
import pandas as pd

log = logging.getLogger("rsi-strategy")
client = TradingClient(API_KEY, API_SECRET, paper=True)

def rsi(series: pd.Series, period: int = 14) -> float:
    delta = series.diff()
    gain = delta.clip(lower=0).rolling(period).mean()
    loss = -delta.clip(upper=0).rolling(period).mean()
    rs = gain / loss
    return float(100 - (100 / (1 + rs.iloc[-1])))

def on_bar(symbol: str, closes: pd.Series) -> None:
    value = rsi(closes)
    pos_qty = get_position_qty(symbol)  # 0 if flat

    if value < 30 and pos_qty == 0:
        log.info("rsi_buy", extra={"symbol": symbol, "rsi": value})
        client.submit_order(MarketOrderRequest(
            symbol=symbol, qty=100,
            side=OrderSide.BUY,
            time_in_force=TimeInForce.DAY,
        ))
    elif value > 70 and pos_qty > 0:
        log.info("rsi_exit", extra={"symbol": symbol, "rsi": value})
        client.submit_order(MarketOrderRequest(
            symbol=symbol, qty=pos_qty,
            side=OrderSide.SELL,
            time_in_force=TimeInForce.DAY,
        ))
// when to use

You want one language for research, backtesting, and live trading. The richest ecosystem for data science and the cleanest broker SDKs in 2026.

// when not to

You need sub-millisecond execution or you live inside a chart-first platform like NinjaTrader.

// runtime
alpaca-py + pandas
↗ official docs
// syntax map — same concept, four languages
conceptPythonPineC#MQL5
Variablex = 10x = 10int x = 10;int x = 10;
Conditionalif rsi < 30:if value < 30if (value < 30) {if (value < 30) {
Buy orderclient.submit_order(MarketOrderRequest(...))strategy.entry("Long", strategy.long)EnterLong(100, "tag");trade.Buy(0.10, _Symbol);
Position sizeqty=100default_qty_value=100EnterLong(100, ...)input double Lots = 0.10;
Logginglog.info('rsi_buy', extra=...)alert("rsi_buy", ...)Print($"rsi_buy ...");PrintFormat("rsi_buy ...");
// 02 · terminal

The shell. Stop being afraid of the black box.

Six categories, fifty commands. Each one has a one-line explanation written for someone who has never opened a terminal. Filter, search, copy — it is built to live in a second monitor while you work.

// cli primer

50 terminal commands every automator should know

Every command is copy-able. Every one has a one-line explanation written for someone who has never opened a shell. Filter or search to find what you need.

// navigate
$ pwd

Print your current working directory. Where am I?

// navigate
$ ls -lah

List every file in the current directory, hidden ones included, with size and date.

// navigate
$ cd ~/projects/bot

Move into a folder. `~` is your home directory.

cd ~ goes home; cd .. goes up one.

// navigate
$ cd -

Jump back to the previous directory you were in. Saves a lot of typing.

// navigate
$ tree -L 2

Show a folder tree two levels deep. Best way to understand a new repo.

Install on macOS: brew install tree

// navigate
$ open .

Open the current folder in Finder (macOS) — useful when you live in the terminal but need to drop a file.

// files
$ cat strategy.py

Dump the whole file to the screen. Fine for short configs, awful for logs.

// files
$ less strategy.py

Scroll through a file one page at a time. Press q to quit, / to search.

// files
$ head -n 50 trades.csv

Show the first 50 lines of a file. Use `tail` for the last 50.

// files
$ tail -f bot.log

Watch a log file grow in real time. Best command in this whole list for live debugging.

// files
$ grep 'ERROR' bot.log

Find every line containing ERROR. Add -r to search a whole folder.

// files
$ find . -name '*.py'

Find every Python file in this folder and its subfolders.

// files
$ wc -l trades.csv

Count the lines in a file. Use to sanity-check 'did all 1000 trades export?'

// files
$ diff a.json b.json

Show what changed between two files. Add -u for the unified diff format devs are used to.

// files
$ cp config.example.yaml config.yaml

Copy a file. `cp -r src/ backup/` copies a whole folder.

// files
$ mv old.py new.py

Rename or move a file. Same command for both.

// files
$ rm trades.csv

Delete a file. No undo. No trash can.

rm -rf is permanent and ruthless. Type the path twice before you press enter.

// processes
$ python bot.py

Run a Python script in the foreground. Ctrl+C stops it.

// processes
$ python bot.py &

Run a Python script in the background. The shell prints a job number.

// processes
$ nohup python bot.py > bot.log 2>&1 &

Run a script in the background AND keep it running after you log out. Output goes to bot.log.

// processes
$ ps aux | grep python

List every Python process running on this machine. Great for 'is my bot actually alive?'

// processes
$ kill 12345

Stop process 12345 politely. If it refuses, use `kill -9 12345` to force-stop.

// processes
$ top

Live dashboard of CPU and memory by process. q to quit. `htop` is the prettier modern version.

// processes
$ watch -n 1 'curl -s localhost:8000/health'

Re-run a command every second. Excellent for watching a healthcheck during deploys.

// processes
$ tmux new -s bot

Open a persistent terminal session called 'bot'. Detach with Ctrl+b then d. Reattach later with `tmux attach -t bot`.

// network
$ curl https://api.alpaca.markets/v2/clock

Fire a single HTTP request and print the response. The Swiss army knife of API testing.

// network
$ curl -X POST -H 'Content-Type: application/json' -d '{...}' URL

POST JSON to an endpoint. The shape every webhook handler should respond to.

// network
$ curl -i URL

Include response headers. Use when you want to see status codes, rate limits, or Content-Type.

// network
$ lsof -i :8000

Which process is holding port 8000? Indispensable when a server won't start.

// network
$ netstat -an | grep LISTEN

List every port your machine is listening on. The honest answer to 'what services do I have running?'

// network
$ ping api.alpaca.markets

Measure round-trip latency to a host. Stop the test with Ctrl+C.

// network
$ dig api.alpaca.markets

Resolve a domain to its IP and see TTL. Helpful when DNS is the bug.

// network
$ ssh ubuntu@your-vps

Connect to a remote machine. Set up SSH keys first; never type the password over and over.

// network
$ scp bot.py ubuntu@vps:~/bot/

Copy a file to a remote server over SSH. Same syntax in reverse to pull files down.

// git
$ git status

What changed since the last commit? The command you run twenty times an hour.

// git
$ git diff

Show every unstaged change line by line. Add `--cached` to see staged changes.

// git
$ git add -p

Stage changes one hunk at a time, accepting or rejecting each. The grown-up way to commit.

// git
$ git commit -m 'risk: cap daily loss at 2%'

Save a snapshot with a message. Keep messages short, present tense, and scoped.

// git
$ git log --oneline -20

Show the last 20 commits, one per line. The fastest way to remember what you shipped.

// git
$ git checkout -b feat/new-strategy

Create and switch to a new branch. Always branch before risky changes.

// git
$ git stash

Set aside uncommitted changes so you can switch branches cleanly. `git stash pop` brings them back.

// git
$ git pull --rebase

Fetch and replay your commits on top of the remote. Cleaner history than a default merge pull.

// python env
$ python --version

Confirm which Python you are about to use. Surprises here cause hours of debugging.

// python env
$ python -m venv .venv

Create an isolated environment in the current folder. Always per-project, never global.

// python env
$ source .venv/bin/activate

Activate the venv. Your prompt usually shows the env name when it worked.

// python env
$ pip install -r requirements.txt

Install every dependency listed in requirements.txt into the active env.

// python env
$ pip freeze > requirements.txt

Write every installed package into requirements.txt so the env is reproducible.

// python env
$ python -m pip install --upgrade pip

Update pip itself. Do this before installing anything else after creating a venv.

// python env
$ python -m pytest tests/

Run the test suite. Run tests before pushing — every time.

// python env
$ python -m ipython

Open a much better Python REPL. Tab completion, history, and rich tracebacks.

Showing 50 of 50 commands.
// 03 · git workflow

Ten steps from clean main to merged PR. The only workflow you need.

You only need ten commands to ship safely. Memorize the order. Internalize the rationale. The cheat sheet covers the other ninety-nine percent of day-to-day work.

// git basics

One feature, ten commands, from clean main to merged PR

This is the only Git workflow you need to memorize. Click any step to see what it does and why it matters. The cheat sheet below covers the other 99% of day-to-day commands.

1
// step 1

Sync main

// command
$ git checkout main && git pull --rebase
// what it does

Start from a clean, up-to-date `main` branch.

// why it matters

If you branch off a stale main, you fight merge conflicts later for no reason.

// gotcha

Always use --rebase on main so your local merges do not pollute history.

Click any other step above to see its rationale. Steps are stacked left-to-right in the order you actually run them.
// cheat sheet

The 20 commands you will actually run

categorycommandwhat it does
Setupgit clone <url>Download a repo for the first time.
Setupgit config user.email 'you@example.com'Set the email attached to every commit you make in this repo.
Dailygit statusWhat has changed since the last commit?
Dailygit diffLine-by-line view of unstaged changes.
Dailygit add <file>Stage one file. `git add -p` stages by hunk.
Dailygit commit -m '...'Snapshot the staged changes.
Dailygit pushSend commits to the remote.
Dailygit pull --rebaseFetch remote and replay your commits on top.
Branchesgit checkout -b nameCreate and switch to a new branch.
Branchesgit branch -d nameDelete a merged local branch.
Branchesgit checkout mainSwitch back to the main branch.
Branchesgit merge nameMerge a branch into the current one.
Historygit log --oneline -20Show the last 20 commits, one per line.
Historygit blame <file>Who last touched each line, and when?
Historygit show <sha>Show the full diff for a commit.
Undogit restore <file>Throw away unstaged changes to a file. No undo.
Undogit reset HEAD <file>Unstage a file without losing your edits.
Undogit commit --amendEdit the last commit. Do NOT amend something you already pushed.
Undogit revert <sha>Add a new commit that undoes an old one. Safe in shared history.
Stashgit stashTuck uncommitted work aside so you can switch branches.
Stashgit stash popBring back the most recent stash.
// 04 · environments

Three environments. From zero to working in under five minutes.

Python venv for 80% of automators. Node + nvm when you build the webhook receiver in JavaScript. Docker Compose when you ship the whole thing as a container. Pick one, copy the commands, verify, move on.

// env setup

From zero to a working environment in three commands or less

Pick the runtime that matches the stack you chose in the Decision Tree. Every command is copy-able. Every step has a one-line explanation of why it exists.

// when to use

You write the strategy in Python, run backtests in pandas, and hit the broker REST API directly. Default for 80% of retail automators.

  1. // step 1
    $ mkdir bot && cd bot

    Make a project folder and step into it. Every bot lives in its own folder.

  2. // step 2
    $ python -m venv .venv

    Create a virtual environment in `.venv`. The leading dot hides it from `ls`.

  3. // step 3
    $ source .venv/bin/activate

    Activate the venv. On Windows PowerShell, use `.\.venv\Scripts\Activate.ps1`. Your prompt should now start with `(.venv)`.

  4. // step 4
    $ python -m pip install --upgrade pip

    Update pip itself before installing anything else. Skips a lot of warnings.

  5. // step 5
    $ pip install alpaca-py pandas python-dotenv

    Install the bare-minimum dependencies for a US-equities bot. Add more as you need them.

  6. // step 6
    $ pip freeze > requirements.txt

    Pin every installed package into requirements.txt. This file gets committed to Git; the .venv folder does not.

  7. // step 7
    $ echo '.venv\n.env\n__pycache__' > .gitignore

    Tell Git to ignore your environment, secrets, and Python cache. Do this on day one.

// verify
$ python -c 'import alpaca; print(alpaca.__version__)'

Prints the installed version. If you see ModuleNotFoundError, your venv is not activated.

// prerequisites
  • macOS or Linux terminal (Windows: use WSL2 or Git Bash)
  • Python 3.10 or newer installed (`python --version` to check)
  • A code editor (VS Code is free and excellent)
// common mistakes
  • `python: command not found`
    On macOS try `python3` instead. On Windows install Python from python.org and check the 'Add to PATH' box during install.
  • `pip install` is hung
    Network or DNS. Add `--default-timeout=60` to pip, or switch to a different network. Corporate VPNs frequently block PyPI.
  • Activated venv but `pip list` is empty
    You activated, then a hook (oh-my-zsh, conda) re-pointed your shell. Run `which python` — it should be inside `.venv/bin/`.
// 05 · debugging playbook

Eight ways your bot will fail. Every one of them happens.

From years of post-mortems: the symptom you actually see, the root causes ranked by likelihood, the diagnostic command, the canonical fix, and how to prevent it from happening again.

// debugging playbook

Eight ways your bot fails. Every one of them happens.

For each scenario: the symptom you actually observe, the root causes ranked by likelihood, the diagnostic command, and the canonical fix. Bookmark this page now — you will be back.

// blast radius

2× position, 2× margin, 2× P&L variance. Risk math is now silently wrong.

// root causes — ranked by likelihood
  1. 1
    No idempotency key on the webhook handler
    Platform retries on 5xx or timeout. Without a dedupe key in Redis, both attempts execute.
  2. 2
    Strategy fires on both bar-close and tick-close
    Common in TradingView Pine when `process_orders_on_close` is true but alerts also fire intra-bar.
  3. 3
    Two instances of the bot running
    You started the bot, restarted it, but never killed the original. `ps aux | grep python` will reveal it.
// diagnose
$ grep -c 'order_submitted' bot.log | head

Count should match the number of signal events. If higher, something is firing twice.

// canonical fix

Wrap order submission in `SETNX <idem_key> EX 60` in Redis. Reject anything you have already seen in the last 60 seconds. This is the #1 risk gate from the flowchart — wire it first.

// prevent it next time

Add a unit test that re-submits the same payload twice and asserts the broker is only called once.

Showing 8 of 8scenarios. Severity is the standard ops scale: Sev 1 means money is moving wrong, Sev 2 means trading is degraded but contained, Sev 3 means everything trades fine, just annoying.
// 06 · printable companion

Take it offline. 31 pages. No login. Free.

The full Coding Fundamentals module, formatted for print or tablet, with every command, every diagram, and every failure scenario in one PDF. Same content as the web — just takes up less screen real estate when you are coding next to it.

// see the library · Module 01

This is one of six modules in the Nexural Automation curriculum. The library page maps every module, shows the dependency graph, and links the master 14-page Curriculum Index PDF.

browse the full PDF library →