
7 Ways to Take Control of Your Legacy
Planning your estate might not sound like the most exciting thing on your to-do list, but trust us, it’s worth it. And with The Investor’s Guide to Estate Planning, preparing isn’t as daunting as it may seem.
Inside, you’ll find {straightforward advice} on tackling key documents to clearly spell out your wishes.
Plus, there’s help for having those all-important family conversations about your financial legacy to make sure everyone’s on the same page (and avoid negative future surprises).
Why leave things to chance when you can take control? Explore ways to start, review or refine your estate plan today with The Investor’s Guide to Estate Planning.
🚀 Your Algo Edge Just Leveled Up — Premium Plans Are Here!🚀
A year in, our Starter, Pro, and Elite Quant Plans are crushing it—members are live-trading bots and booking 1-on-1 wins. Now with annual + lifetime deals for max savings.
Every premium member gets: ✅ Full code from every article ✅ Private GitHub repos + templates ✅ 3–5 deep-dive paid articles/mo ✅ Early access + live strategy teardowns
Pick your edge:
Starter (€20/mo) → 1 paid article + public repos
Builder (€30/mo) → Full code + private repos (most popular)
Master (€50/mo) → Two 1-on-1 calls + custom bot built for you
Best deals: 📅 Annual: 2 months FREE 🔒 Lifetime: Own it forever + exclusive perks
First 50 annual/lifetime signups get a free 15-min audit. Don’t wait—the market won’t.
— AlgoEdge Insights Team
Today we are trying to learn to implement a proper momentum trading strategy, i.e. how to set up the trading signals, implement the trade, and optimizing for the best period to hit the trade.
What we are trying to learn?
Basic use of classes
Setting up signals and plotting them
Comparing performance
Optimizing for the best momentum signal
At the end of the day, we want to set up a Simple Moving Average, buy if the price is above it, and close our position once it goes below it. We then want to see what is the BEST Simple Moving Average.
Code
The full end-to-end workflow is available in a Google Colab notebook, exclusively for paid subscribers of my newsletter. Paid subscribers also gain access to the complete article, including the full code snippet in the Google Colab notebook, which is accessible below the paywall at the end of the article. Subscribe now to unlock these benefits!
Setting Up The Class
First, we set up a class that plays our momentum trading strategy. This class takes in our closing price data, our expected number of days moving average, our initial capital and our transaction cost multiplier:
class Momentum:
def __init__(self, data, x, init, tran_cost):
self.data = pd.DataFrame(data, columns=["Close"])
self.x = x # number of days to calculate moving average
self.init = init # initial capital
self.tran_cost = tran_cost # transaction cost as a fractionWe then set up a function within this class that calculates the moving average based on some X trading days:
def SMA(self):
"""
Calculate the Simple Moving Average (SMA) based on x days
Returns:
pd.Series: Simple Moving Average (SMA) based on x days and fills NaN values with Close prices of the same day
"""
return self.data["Close"].rolling(window=self.x).mean().fillna(self.data["Close"])Note that here we fill periods where the moving average cannot yet be calculated with that day’s price because we do not want trades before we can calculate the moving average.
Following that, we can implement our trade function. This would be more unruly but what we are essentially doing is:
We take the data and calculate the desired Simple Moving Average.
Set up our dataframe to keep track of our Position Value, Shares Currently Held, Transaction Cost Paid, Cash Available at any point in time
Set up a signal to denote when we should or should not trade
We do this by demarcating points in time where the close price is above SMA with 1, then using the
diff()function to calculate how our signal has changedThat should give us
1on the points where we need to buy and-1on the points we need to close our positionNow, using a for loop, iterate to trade accordingly and update our position, shares, cost and cash trackers.
Create new columns where we calculate the returns for the index as well as the momentum trading strategy.
def trade(self):
"""
Simulate trading based on the moving average strategy
Returns:
pd.DataFrame: DataFrame containing new columns for:
- trading signals
- positions
- shares
- cash
- transaction costs
- returns
- cumulative returns
"""
data = self.data.copy()
data.index = pd.to_datetime(data.index)
data["SMA"] = self.SMA()
# Initialize portfolio, shares, cash, and transaction cost
data["Position"] = 0
data["Shares"] = 0
data["Tran_Cost"] = 0
data["Cash"] = 0
data["Cash"].iloc[0] = self.init
data["Position"].iloc[0] = self.init
# check if price is above or below moving average using pandas
data["Signal"] = np.where(data["Close"] > data["SMA"], 1, 0)
data["Signal"] = data["Signal"].diff().fillna(0)
data["Buy"] = np.where(data["Signal"] == 1, data["Close"], np.nan)
data["Sell"] = np.where(data["Signal"] == -1, data["Close"], np.nan)
# Calculate shares and cash
for i in range(1, len(data)):
if data["Signal"].iloc[i] == 1:
# buy as many shares whole (non decimal) as funds allow
data["Shares"].iloc[i] = data["Cash"].iloc[i - 1] // (data["Close"].iloc[i] * (1 + self.tran_cost))
data["Tran_Cost"].iloc[i] = data["Shares"].iloc[i] * data["Close"].iloc[i] * self.tran_cost
data["Cash"].iloc[i] = data["Cash"].iloc[i - 1] - data["Shares"].iloc[i] * data["Close"].iloc[i] - data["Tran_Cost"].iloc[i]
data["Position"].iloc[i] = data["Shares"].iloc[i] * data["Close"].iloc[i] + data["Cash"].iloc[i]
elif data["Signal"].iloc[i] == -1:
data["Cash"].iloc[i] = data["Cash"].iloc[i - 1] + data["Shares"].iloc[i - 1] * data["Close"].iloc[i] * (1 - self.tran_cost)
data["Shares"].iloc[i] = 0
data["Position"].iloc[i] = data["Cash"].iloc[i]
else:
data["Cash"].iloc[i] = data["Cash"].iloc[i - 1]
data["Shares"].iloc[i] = data["Shares"].iloc[i - 1]
data["Position"].iloc[i] = data["Shares"].iloc[i] * data["Close"].iloc[i] + data["Cash"].iloc[i]
# Calculate returns and cumulative returns
data["Returns"] = data["Position"].pct_change().fillna(0)
data["Cum_Returns"] = (1 + data["Returns"]).cumprod()
# index returns for comparison
data["Index_Returns"] = data["Close"].pct_change().fillna(0)
data["Index_Cum_Returns"] = (1 + data["Index_Returns"]).cumprod()
self.data = data
return dataNow what we can do to test this function is apply it to S&P500 Index (SPX Index). To do this, we pull the SPX data from Yahoo Finance since inception and initialize the Momentum class using:
200 Day Moving Average
Initial Capital of $1 Million
0.1% Transaction Cost
import yfinance as yf
# pull SPX data from Jan 1928
spx = yf.Ticker("^GSPC")
spx_close = spx.history(start="1928-01-01")["Close"]
# Initialize the Momentum class
trade = Momentum(spx_close, 200, 1000000, 0.001)
trade.trade()This should give us something like the following:

Signal Plotting Function
Now, how do we plot the following? Using the Buy or Sell signal we’ve used…
Subscribe to our premium content to read the rest.
Become a paying subscriber to get access to this post and other subscriber-only content.
Upgrade


