Welcome to the first blog post in a new series introducing our upcoming book, “Hands-On AI Trading with Python, QuantConnect, and AWS.”
In today’s post, we’re exploring the world of Bitcoin—an asset renowned for its volatility and even more spectacular opportunity. We often ask:
“What if we had a perfect crystal ball telling us whether BTCUSD’s price would rise tomorrow?”
Since Bitcoin captured global attention, predicting the price of BTCUSD has been a widely discussed topic. While many approaches focus on technical indicators, macro events, or AI-based price forecasting, it’s helpful to understand the best-case scenario for a trading strategy holding Bitcoin for at most one day if every daily decision (buy or sell) was correct.
Such a strategy:
- Buys at today’s close and sells at tomorrow’s close only if tomorrow’s price rise is significant enough to cover fees.
- Ignores any “guesswork” about sideways moves or partial signals—if tomorrow’s close is guaranteed to be higher than today’s by a margin above the transaction costs, we take the trade.
- Accumulates capital multiplicatively across all profitable days.
This approach is unrealistic in real-time trading, yet it tells us what the upper bound might be if we could reliably outsmart the market’s short-term fluctuations.
QuantConnect provides a powerful Research Environment where you can write Python code, fetch historical data instantly, and run flexible experiments. It’s an ideal sandbox to test hypothetical or advanced prototypes before turning them into complete trading algorithms.
Code: Perfect Foresight Daily Strategy
Below is a snippet you can copy-paste into a QuantConnect Research Notebook. It does the following:
- Sorts daily closing prices for BTCUSD.
- Iterates from day i to day i+1.
- Checks if tomorrow’s price is sufficiently higher than today’s to cover transaction fees (e.g., 1% total).
- If profitable, executes a hypothetical buy at today’s close and sell at tomorrow’s close, updating your capital.
- Returns your final capital multiple and a list of trades (buy date, buy price, sell date, sell price, net return, etc.).
def perfect_foresight_daily_with_orders(prices: pd.Series, round_trip_fee_pct: float):
"""
Simulates a perfect-foresight strategy that decides daily whether
to buy today's close and sell tomorrow's close, if profitable after fees.
This version also returns a list of all executed trades with details.
Parameters
----------
prices : pd.Series
Daily closing prices, with a DateTimeIndex or similar
round_trip_fee_pct : float
Total transaction fee (fraction) for a buy+sell round trip.
e.g. 0.01 => 1% total for buy+sell
Returns
-------
final_capital : float
Growth factor of 1 initial capital after all trades
trades : pd.DataFrame
A DataFrame (or list) of all trades made, with columns:
- "BuyDate", "BuyPrice"
- "SellDate", "SellPrice"
- "GrossReturn"
- "NetReturn"
- "CapitalBefore"
- "CapitalAfter"
"""
capital = 1.0
trades_list = []
# Sort the Series chronologically just in case
prices = prices.sort_index()
price_values = prices.values
price_index = prices.index
for i in range(len(prices) - 1):
p_t = price_values[i]
p_t1 = price_values[i + 1]
gross_return = p_t1 / p_t
# Check if after subtracting fees the trade is profitable
# We'll require (gross_return - 1) > round_trip_fee_pct
if (gross_return - 1) > round_trip_fee_pct:
net_return = gross_return * (1 - round_trip_fee_pct)
# Record the trade details
trade_info = {
"BuyDate": price_index[i],
"BuyPrice": p_t,
"SellDate": price_index[i + 1],
"SellPrice": p_t1,
"GrossReturn": gross_return,
"NetReturn": net_return,
"CapitalBefore": capital, # capital before trade
}
# Update capital
capital = capital * net_return
trade_info["CapitalAfter"] = capital
trades_list.append(trade_info)
# Convert the trades list to a DataFrame for easier inspection
trades_df = pd.DataFrame(trades_list)
return capital, trades_df
Trying It Out
In your QuantConnect Research Notebook:
- Load BTCUSD data (daily resolution) from your chosen date range.
- Call the
perfect_foresight_daily_with_orders
function with your price series and a chosen fee (e.g., 1% = 0.01). - Inspect the final capital multiple and the DataFrame of trades to see which days triggered a buy/sell.
Example usage with a comparison of the algorithm for BTC on Coinbase and SPY on Interactive Brokers.
# 1) BTC on Coinbase: ~1.0% round-trip if we assume 0.5% each side
coinbase_round_trip_fee = 0.01 # 1.0%
btc_final_cap, btc_trades_df = perfect_foresight_daily_with_orders(btc_close, 0.01)
# 2) SPY on Interactive Brokers: ~0.02% round-trip if we assume 0.01% each side
ib_round_trip_fee = 0.0002 # 0.02%
spy_final_cap, spy_trades_df = perfect_foresight_daily_with_orders(spy_close, ib_round_trip_fee)
print(f"Perfect foresight strategy final return (BTC): {btc_final_cap:.2f}x")
print(f"Perfect foresight strategy final return (SPY): {spy_final_cap:.2f}x")
print()
print("BTCUSD Trades executed:\n", btc_trades_df)
The output is
Perfect foresight strategy final return (BTC): 67.58x
Perfect foresight strategy final return (SPY): 9.74x
BTCUSD Trades executed:
BuyDate BuyPrice SellDate SellPrice GrossReturn NetReturn \
0 2022-01-11 41824.07 2022-01-12 42753.44 1.022221 1.011999
1 2022-01-12 42753.44 2022-01-13 43920.37 1.027294 1.017021
2 2022-01-14 42581.65 2022-01-15 43090.72 1.011955 1.001836
3 2022-01-23 35066.43 2022-01-24 36282.47 1.034678 1.024331
4 2022-01-24 36282.47 2022-01-25 36693.32 1.011324 1.001210
.. ... ... ... ... ... ...
208 2023-12-13 41477.39 2023-12-14 42885.54 1.033950 1.023610
209 2023-12-18 41349.59 2023-12-19 42650.01 1.031449 1.021135
210 2023-12-20 42266.22 2023-12-21 43674.77 1.033326 1.022992
211 2023-12-25 43025.03 2023-12-26 43589.67 1.013124 1.002992
212 2023-12-27 42515.53 2023-12-28 43474.40 1.022553 1.012328
CapitalBefore CapitalAfter
0 1.000000 1.011999
1 1.011999 1.029224
2 1.029224 1.031114
3 1.031114 1.056202
4 1.056202 1.057481
.. ... ...
208 62.249193 63.718916
...
211 66.561625 66.760797
212 66.760797 67.583815
[213 rows x 8 columns]
Interpreting the Results
- The output shows a return on BTC of 67.58% and on SPY of 9.74% after fees for the trading period from Jan 1, 2022, to Jan 1, 2024.
- The btc_trades_df DataFrame highlights each day where tomorrow’s close was high enough to justify a trade. You’ll see “BuyDate,” “SellDate,” the “GrossReturn” (price ratio), the final “NetReturn” after fees, and how your capital changed.
Realism Check
- No one has perfect foresight. This is purely hypothetical.
- Fees & Slippage: In actual trading, you might face higher transaction costs, partial fills, or slippage—especially in volatile crypto markets.
- Practical Strategies typically use signals (technical indicators, machine learning forecasts, etc.). Imperfect predictions lower returns drastically but allow traders to trade in real-time.
The Bigger Picture: AI and BTC
Bitcoin’s volatility often provides abundant intraday or day-to-day fluctuations, making it enticing for short-term or swing trading. Day-ahead predictions tend to be more reliable than week-ahead forecasts, enhancing the appeal of short-term strategies.
By examining a perfect foresight scenario, we establish an upper limit on how effectively an algorithm could take advantage of daily price moves. In real-world trading, you might aim to approximate that ideal performance using sophisticated indicators, machine-learning techniques, or event-based signals.