Skip to content
GetProfitable
Search

Python and virtual environments

Lesson 1 · about 10 min

Algorithmic trading is mostly plumbing. The strategy is a few dozen lines; the other few thousand are loading data, checking it, running it through a backtest, and getting orders to a broker without anything silently going wrong. Python is the default language for this work because pandas and numpy make the data plumbing short, and because every broker with an API has a Python client. This course assumes you can already trade by hand and have written at least a little code in any language. It does not assume you know Python well.

Which Python

Install Python 3.11 or newer from python.org or, on macOS and Linux, through your package manager. Avoid the copy of Python that ships with the operating system; it is used by system tools and you do not want to install packages into it. On Windows, tick "Add python.exe to PATH" during the installer.

Check it worked:

python3 --version

You should see Python 3.11.x or later. If python3 is not found on Windows, try py --version.

One venv per project, always

A virtual environment (venv) is a private folder of packages that belongs to one project. Without one, every project on your machine shares a single set of packages, and the day you upgrade pandas for a new project is the day your old backtest starts producing different numbers.

Create and activate one:

mkdir algo-course && cd algo-course
python3 -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows (PowerShell)
.venv\Scripts\Activate.ps1

Your prompt now shows (.venv). Everything you pip install from here goes into .venv/ and nowhere else. Deactivate with deactivate. If you close the terminal, you must activate again; forgetting to is the single most common "it worked yesterday" bug.

Install the packages this course uses:

pip install --upgrade pip
pip install pandas numpy matplotlib pyarrow jupyter

That is the whole dependency list for modules 1 through 8. pyarrow is for parquet files (Module 2). Broker clients come later and only when you need them.

Pin what you installed

Once things work, write down exactly which versions you have:

pip freeze > requirements.txt

The file lists every package with an exact version, for example pandas==2.2.2. Anyone (including you, on a new laptop) can reproduce the environment with:

pip install -r requirements.txt

Commit requirements.txt to git. Do not commit .venv/; add it to .gitignore.

Key idea: A backtest result is only meaningful if you can rerun it and get the same number. That starts with knowing exactly which versions of which packages produced it.

A first script

Make a file called hello_prices.py and run it with python hello_prices.py. This generates a synthetic price series so nothing in the course depends on a download working.

import numpy as np
import pandas as pd


def synthetic_prices(n: int = 250, seed: int = 42, start: float = 100.0) -> pd.Series:
    """Geometric random walk of daily closes on business days."""
    rng = np.random.default_rng(seed)
    daily_returns = rng.normal(loc=0.0003, scale=0.012, size=n)
    closes = start * np.exp(np.cumsum(daily_returns))
    index = pd.bdate_range("2024-01-01", periods=n)
    return pd.Series(closes, index=index, name="close")


if __name__ == "__main__":
    prices = synthetic_prices()
    print(prices.head())
    print(f"{len(prices)} bars, first {prices.index[0].date()}, last {prices.index[-1].date()}")
    print(f"total return: {prices.iloc[-1] / prices.iloc[0] - 1:.2%}")

A few things to notice, because they recur throughout the course. np.random.default_rng(seed) is the modern way to get reproducible randomness: same seed, same series, every run. pd.bdate_range makes a business-day index, so the series has weekday dates like real stock data. The if __name__ == "__main__": guard means the function can be imported by other files without running the demo.

You will see synthetic_prices (and a fuller synthetic_ohlcv from Module 3 onwards) at the top of many lessons. It is repeated on purpose so every code block runs on its own.

When something breaks

Three checks solve most environment problems:

  1. Is the venv active? Look for (.venv) in the prompt.
  2. Is the right Python running? which python (or where python on Windows) should point inside .venv.
  3. Is the package actually installed there? pip list | grep pandas.

If you use an editor like VS Code, point its interpreter setting at .venv/bin/python so that running a file from the editor uses the same packages as your terminal.

Try it: Create the venv, install the packages, run hello_prices.py, then change the seed to 7 and run it again. Confirm the total return changed. Change it back to 42 and confirm you get the original number exactly. That round trip is what reproducibility means.

Recap

  • Use Python 3.11+ from python.org or a package manager, never the operating system's copy.
  • One virtual environment per project; activate it before every session.
  • pip freeze > requirements.txt pins versions so results can be reproduced.
  • Seeded random generators give the same synthetic data every run.
  • Most "it stopped working" problems are an inactive venv or the wrong interpreter.

See it drawn

Original diagrams for the ideas on this page. Illustrative, not real market data.

A range beside a trendOne chart swinging between a flat floor and ceiling, another stepping upwards inside a pair of sloping lines.Range-boundresistancesupportprice bounces between two levelsTrendingthe trend channelhigher highs and higher lowsA range has two flat edges; a trend has two sloping ones.
Range versus trend. On the left price keeps bouncing between the same floor and ceiling, which is a range. On the right each high and each low is higher than the last, inside a pair of sloping lines called a channel.