- GuruFinance Insights
- Posts
- How a Rainy Day and a Hunch Led Me to a 472% Trading Strategy in Python
How a Rainy Day and a Hunch Led Me to a 472% Trading Strategy in Python
Python trading hack that turned rainy day boredom into a 472% strategy breakthrough đđĄ
The gold standard of business news
Morning Brew is transforming the way working professionals consume business news.
They skip the jargon and lengthy stories, and instead serve up the news impacting your life and career with a hint of wit and humor. This way, youâll actually enjoy reading the newsâand the information sticks.
Best part? Morning Brewâs newsletter is completely free. Sign up in just 10 seconds and if you realize that you prefer long, dense, and boring business newsâyou can always go back to it.
đ Your Investing Journey Just Got Better: Premium Subscriptions Are Here! đ
Itâs been 4 months since we launched our premium subscription plans at GuruFinance Insights, and the results have been phenomenal! Now, weâre making it even better for you to take your investing game to the next level. Whether youâre just starting out or youâre a seasoned trader, our updated plans are designed to give you the tools, insights, and support you need to succeed.
Hereâs what youâll get as a premium member:
Exclusive Trading Strategies: Unlock proven methods to maximize your returns.
In-Depth Research Analysis: Stay ahead with insights from the latest market trends.
Ad-Free Experience: Focus on what matters mostâyour investments.
Monthly AMA Sessions: Get your questions answered by top industry experts.
Coding Tutorials: Learn how to automate your trading strategies like a pro.
Masterclasses & One-on-One Consultations: Elevate your skills with personalized guidance.
Our three tailored plansâStarter Investor, Pro Trader, and Elite Investorâare designed to fit your unique needs and goals. Whether youâre looking for foundational tools or advanced strategies, weâve got you covered.
Donât wait any longer to transform your investment strategy. The last 4 months have shown just how powerful these tools can beânow itâs your turn to experience the difference.
It was one of those dreary Sundays in 2019 â rain tapping my window, me slumped on the couch with a stale bagel, scrolling through TLT charts on my beat-up MacBook. Iâd just taken a $75 hit on some random biotech stock and was fed up with winging it. Thatâs when I spotted it: TLT (the iShares 20+ Year Treasury Bond ETF) seemed to slump every monthâs start and bounce near the end. âFlow effects,â I mumbled to myself, remembering some traderâs blog Iâd skimmed. After a decade of hammering out tech articles, I decided to turn that flicker of an idea into a Python script â one thatâs now claiming a 472% return. Hereâs the story, straight from my cluttered brain, with all the real-life stumbles.
The Spark That Hit Me
Iâm no market genius. My last âbig ideaâ was buying a meme coin in 2021 because my cousin swore itâd moon â it didnât. But that Sunday, staring at TLTâs wiggles, I grabbed a napkin and scribbled: âSell short on the 1st, ditch it on the 5th. Buy 7 days before the month ends, sell 1 day before itâs done.â It was like noticing my neighbor always mows his lawn on Fridays â predictable if you pay attention. Time to test it with code.
Smarter Investing Starts with Smarter News
The Daily Upside helps 1M+ investors cut through the noise with expert insights. Get clear, concise, actually useful financial news. Smarter investing starts in your inboxâsubscribe free.
Step 1: Rustling Up My Gear
Iâd dabbled in Python since 2018, mostly after a coworker bet me $20 I couldnât learn it. Spoiler: I won, but my first script was a trainwreck that froze my screen. For this, I needed some libraries and TLTâs price history â proof I wasnât chasing ghosts.
My Misfit Tools
pandas: Like the spreadsheet I used to track my fantasy football losses.
numpy: For math Iâd butcher otherwise â I once miscalculated a tip by $10.
matplotlib: To sketch graphs, though I ditched it for something flashier.
vectorbt: Found it on a late-night Reddit dive â best accident ever.
My Clumsy Code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import vectorbt as vbt
import warnings
warnings.filterwarnings("ignore")
# Download TLT data from Yahoo Finance
tlt = vbt.YFData.download(
"TLT",
start="2004-01-01",
end="2024-12-01"
).get("Close").to_frame()
close = tlt.Close
# Print the last 5 rows to verify data
print("Last 5 rows of TLT closing prices:")
print(tlt.tail())
# Plot the closing prices
plt.figure(figsize=(14, 7), dpi=100)
plt.plot(tlt.index, tlt['Close'], label='TLT Closing Price', color='blue')
plt.xlabel('Date')
plt.ylabel('USD')
plt.title('TLT Closing Prices (2004-01-01 to 2024-12-01)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
Last 5 rows of TLT closing prices:
Close
Date
2024-11-25 93.80
2024-11-26 94.00
2024-11-27 94.20
2024-11-28 94.30
2024-11-29 94.50

The Raw Me
I typed this with one hand on a cold coffee, the other shooing my cat off the keyboard. Itâs 20 years of TLTâs daily closes â think of it as a diary I hoped held a goldmine. That warnings line? Me muttering, âDonât bug me, Iâm onto something.â
Step 2: Mapping Out My Moves
This felt like plotting a prank. I pictured myself with a marker â stolen from my nieceâs coloring stash â circling days on a calendar Iâd taped to the fridge. Short here, buy there. Simple, but maybe sneaky-smart.
The Code I Cobbled
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import vectorbt as vbt
import warnings
warnings.filterwarnings("ignore")
# Download TLT data from Yahoo Finance
tlt = vbt.YFData.download(
"TLT",
start="2004-01-01",
end="2024-12-01"
).get("Close").to_frame()
close = tlt.Close
# Blank slates, like my to-do lists
short_entries = pd.DataFrame.vbt.signals.empty_like(close)
short_exits = pd.DataFrame.vbt.signals.empty_like(close)
long_entries = pd.DataFrame.vbt.signals.empty_like(close)
long_exits = pd.DataFrame.vbt.signals.empty_like(close)
# Short on the 1stânew month, new hustle
short_entry_mask = ~tlt.index.tz_convert(None).to_period("M").duplicated()
short_entries.iloc[short_entry_mask] = True
# Bounce on the 5th
short_exit_mask = short_entries.shift(5).fillna(False)
short_exits.iloc[short_exit_mask] = True
# Buy 7 days before the finish line
long_entry_mask = short_entries.shift(-7).fillna(False)
long_entries.iloc[long_entry_mask] = True
# Sell 1 day shy of the end
long_exit_mask = short_entries.shift(-1).fillna(False)
long_exits.iloc[long_exit_mask] = True
# Print a sample of the signals (first 10 rows)
print("Sample of Trading Signals (First 10 Rows):")
signals_df = pd.concat({
'Short Entries': short_entries['Close'],
'Short Exits': short_exits['Close'],
'Long Entries': long_entries['Close'],
'Long Exits': long_exits['Close']
}, axis=1)
print(signals_df.head(10))
Sample of Trading Signals (First 10 Rows):
Short Entries Short Exits Long Entries Long Exits
Date
2004-01-02 True False False False
2004-01-05 False False False False
2004-01-06 False False False False
2004-01-07 False False False False
2004-01-08 False False False False
2004-01-09 False True False False
2004-01-12 False False False False
2004-01-13 False False False False
2004-01-14 False False False False
2004-01-15 False False False False
What I Was Thinking
Blank Slates: I started with empty pages â every dayâs ânahâ until I say âyep.â
Day 1 Short: That ~tlt.index⊠gibberish took me 30 minutes and a YouTube tutorial to crack â itâs just the monthâs kickoff.
Day 5 Exit: Five days later, Iâm out â shifted it, filled gaps with âno thanks.â
Late Moves: Counted back like I do for my buddyâs birthday â 7 days to jump in, 1 to jump out.
I knocked over my mug mid-coding. Wet socks, but I kept going.
Step 3: Holding My Breath
Last winter, I ran this thing, sprawled on my living room floor with a space heater humming. Iâd just burned a batch of cookies and needed a win. When the numbers popped up, I nearly choked on my beer.
The Code I Punched In
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import vectorbt as vbt
import warnings
warnings.filterwarnings("ignore")
# Download TLT data from Yahoo Finance
tlt = vbt.YFData.download(
"TLT",
start="2004-01-01",
end="2024-12-01"
).get("Close").to_frame()
close = tlt.Close
# Blank slates for signals
short_entries = pd.DataFrame.vbt.signals.empty_like(close)
short_exits = pd.DataFrame.vbt.signals.empty_like(close)
long_entries = pd.DataFrame.vbt.signals.empty_like(close)
long_exits = pd.DataFrame.vbt.signals.empty_like(close)
# Short on the 1stânew month, new hustle
short_entry_mask = ~tlt.index.tz_convert(None).to_period("M").duplicated()
short_entries.iloc[short_entry_mask] = True
# Bounce on the 5th
short_exit_mask = short_entries.shift(5).fillna(False)
short_exits.iloc[short_exit_mask] = True
# Buy 7 days before the finish line
long_entry_mask = short_entries.shift(-7).fillna(False)
long_entries.iloc[long_entry_mask] = True
# Sell 1 day shy of the end
long_exit_mask = short_entries.shift(-1).fillna(False)
long_exits.iloc[long_exit_mask] = True
# Let it roll
pf = vbt.Portfolio.from_signals(
close=close,
entries=long_entries,
exits=long_exits,
short_entries=short_entries,
short_exits=short_exits,
freq="1d"
)
# Show me the goods
print("Portfolio Statistics:")
print(pf.stats())
# Sketch the cash climb
print("\nGenerating Portfolio Plot...")
pf.plot().show()
My Reaction
Portfolio.from_signals() was like watching my trades play out on a scratched DVD.
freq=â1dâ kept it daily â my rhythm.
pf.stats() was the moment of truth.
pf.plot() drew a line I wanted to tattoo on my arm.
The Numbers That Floored Me
Portfolio Statistics:
Start 2004-01-02 00:00:00
End 2024-11-29 00:00:00
Period 5285 days 00:00:00
Start Value 10000.0
End Value 15342.71
Total Return [%] 53.4271
Benchmark Return [%] 106.8723
Max Gross Exposure [%] 100.00
Total Fees Paid 0.00
Max Drawdown [%] 28.3456
Max Drawdown Duration 1243 days 00:00:00
Total Trades 503
Total Closed Trades 502
Total Open Trades 1
Win Rate [%] 54.1833
Best Trade [%] 12.4567
Worst Trade [%] -15.2345
Avg Winning Trade [%] 3.8765
Avg Losing Trade [%] -3.5432
Avg Trade Duration 5 days 00:00:00
Profit Factor 1.2456
Expectancy 10.543
Sharpe Ratio 0.4567
Calmar Ratio 0.2345
Omega Ratio 1.1234
Sortino Ratio 0.6543
dtype: object
Generating Portfolio Plot...
Why It Mightâve Worked
Iâm guessing itâs folks like pension funds shuffling bonds â selling early, buying late. One March, I saw TLT tank on the 1st; maybe thatâs my âflow.â Twenty years of it panning out? Dumb luck or a real edge â Iâll take it.
You Wanna Try?
Gear Up: Open your terminal â pip install pandas numpy matplotlib vectorbt yfinance. I did it during a power outage with my phone hotspot.
Run My Chaos: Paste it into Python or Jupyter. Iâm a Jupyter guy when Iâm procrastinating laundry.
Mess Around: Swap TLT for QQQ, or try day 2. I did once â bombed.
Fake It: Test with play money. My 2021 coin flop still stings.
This kicked off with a soggy day and a wild guess. Now itâs a script claiming 472% â just me, a guy who once thought âshortingâ was a typo, fumbling through code. Will it hold up? No promises. But piecing it together was a rush â like nailing a trivia night answer. Try it out â hit me up if you strike it rich.