- 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.
Read The Daily Upside. Stay Ahead of the Markets. Invest Smarter.
Most financial news is full of noise. The Daily Upside delivers real insights—clear, concise, and free. No clickbait, no fear-mongering. Just expert analysis that helps you make smarter investing decisions.
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.