liveBook · Manning

Trading strategy

As explained in Investing for Programmers

A trading strategy is a defined method for buying and selling assets to pursue specified market objectives.

A trading strategy is a defined method for buying and selling assets to pursue a market objective. It turns signals, timing rules, position size, and costs into repeatable decisions that can be tested against historical prices. section 11.3.1 section 1.3.4

A simple strategy can be implemented as a sequence of explicit rules:

  • Calculate short- and long-window simple moving averages from closing prices. section 11.3.1
  • Buy when the shorter average crosses above the longer average, and sell when it crosses below. section 11.3.1
  • Fix the investment amount and share quantity, then account for transaction costs when measuring gains. section 11.3.1
  • Compare parameter choices and assets rather than treating one historical result as a guarantee. section 11.3.1

SMA crossover backtest

A Python workflow loads historical prices, adds 10-day and 20-day SMAs to a pandas DataFrame, records alternating buy and sell actions, and sums cash movements after costs. Testing alternative windows on NVIDIA data produces different gains, while comparisons across KO, MMM, PFE, AAPL, and MSFT show that outcomes vary by asset. section 11.3.1

Listing 11.1 Backtest
def backtest(df: pd.DataFrame, lower: int, upper: int, shares : int, 
  buy_first_day = False) -> pd.DataFrame:
    schema={'date': 'datetime64[ns]', 'action': 'str', 'cash_movement':
 'float64'}
    results = pd.DataFrame(columns=schema.keys()).astype(schema)
    if buy_first_day:
        results.loc[len(results)] = [df["Date"].iloc[0], "Buy", 
df["Close"].iloc[0] * shares * -1]
        waiting_for_bear = True
    else:
        waiting_for_bear = False

    for index, row in df.iterrows():
        if not waiting_for_bear:
            if row[f"sma_{lower}"] > row[f"sma_{upper}"]:
                results.loc[len(results)] = [row.Date, "Buy", 
                   row.Close * shares * -1]
                waiting_for_bear = True
        if waiting_for_bear:
            if row[f"sma_{lower}"] < row[f"sma_{upper}"]:
                results.loc[len(results)] = [row.Date, 
                                             "Sell", 
                                             row.Close * shares]
                waiting_for_bear = False
    if waiting_for_bear:
        results.loc[len(results)] = [df["Date"].iloc[-1], "Sell", 
df["Close"].iloc[-1] * shares]
    return results

Inspect the backtest implementation that converts SMA signals into dated actions and cash movements. section 11.3.1

How Investing for Programmers covers it

How deep it goes
Explains SMA signals, position sizing, transaction costs, and parameter tests, while deferring short selling to advanced scenarios.
Examples
Uses SMA crossover rules, pandas DataFrames, NVIDIA price data, transaction-cost calculations, and cross-company result tables.
What it assumes
Assumes moving-average signals and historical price data as working inputs, while keeping the trading rules simple.
What you can do after
Build it from scratch with pandas and historical ticker data, then compare parameterized backtests after transaction costs.
How it connects
Connects technical analysis, moving averages, backtesting, portfolios, and income investing.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Investing for Programmers. The section links point to the parts of the book it draws on.