🐍 QuantConnect Python Script: Smoothed Oscillator Strategy
python
Copy
Edit
from AlgorithmImports import *
import math
import numpy as np
class SmoothedOscillatorStrategy(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 1, 1)
self.SetCash(100000)
self.symbols = ["AAPL", "MSFT", "NVDA"] # Replace with up to 20 symbols
# Per-symbol configs (can be AI-optimized later)
self.symbol_config = {
"AAPL": {"lookback": 20, "cycle": 10, "smoothing": 0.2, "resolution": 45},
"MSFT": {"lookback": 30, "cycle": 12, "smoothing": 0.3, "resolution": 60},
"NVDA": {"lookback": 25, "cycle": 15, "smoothing": 0.25, "resolution": 45}
self.oscillators = {}
for ticker in self.symbols:
symbol = self.AddEquity(ticker, Resolution.Minute).Symbol
config = self.symbol_config[ticker]
res_minutes = config["resolution"]
consolidator = TradeBarConsolidator(timedelta(minutes=res_minutes))
consolidator.DataConsolidated += self.OnConsolidated
self.SubscriptionManager.AddConsolidator(symbol, consolidator)
self.oscillators[symbol] = {
"window": RollingWindow[TradeBar](config["lookback"]),
"value": 0,
"smoothed": None,
"entry_price": None,
"position": None # "long" / "short" / None
def OnConsolidated(self, sender, bar):
symbol = bar.Symbol
config = self.symbol_config[symbol.Value]
osc = self.oscillators[symbol]
osc["window"].Add(bar)
if not osc["window"].IsReady:
return
prices = [x.Close for x in osc["window"]]
high = max(prices)
low = min(prices)
price_range = high - low
std_dev = np.std(prices)
current_price = prices[-1]
if price_range == 0:
osc_val = 0
else:
normalized = (current_price - low) / price_range * 2.4 - 1.2
bar_index = self.Time.minute + self.Time.hour * 60 # crude bar clock
cycle = math.sin(2 * math.pi * bar_index / config["cycle"])
weighted = normalized * (1 + 0.5 * cycle + 0.3 * std_dev / price_range)
# Smoothing
if osc["smoothed"] is None:
osc["smoothed"] = weighted
else:
s = config["smoothing"]
osc["smoothed"] = osc["smoothed"] * (1 - s) + weighted * s
osc_val = max(-1.2, min(1.2, osc["smoothed"]))
osc["value"] = osc_val
self.HandleSignal(symbol, osc_val)
def HandleSignal(self, symbol, osc_val):
holdings = self.Portfolio[symbol]
ticker = symbol.Value
config = self.symbol_config[ticker]
# Entry short
if osc_val >= 1 and not holdings.Invested:
self.SetHoldings(symbol, -1)
self.Debug(f"{self.Time}: SHORT {ticker} @ {self.Securities[symbol].Price}")
# Exit short (smoothed delayed exit)
elif osc_val <= -1 and holdings.IsShort:
self.Liquidate(symbol)
self.Debug(f"{self.Time}: COVER {ticker} @ {self.Securities[symbol].Price}")
# Entry long
elif osc_val <= -1 and not holdings.Invested:
self.SetHoldings(symbol, 1)
self.Debug(f"{self.Time}: LONG {ticker} @ {self.Securities[symbol].Price}")
# Exit long (smoothed delayed exit)
elif osc_val >= 1 and holdings.IsLong:
self.Liquidate(symbol)
self.Debug(f"{self.Time}: SELL {ticker} @ {self.Securities[symbol].Price}")
3. How to Modify These Parameters as the Programmer?
You can do it in three easy ways, depending on how much automation you want.
Option A: 🔧 Manual Editing Inside QuantConnect
Just edit this dictionary in your code:
python
Copy
Edit
self.symbol_config["AAPL"]["smoothing"] = 0.35
self.symbol_config["AAPL"]["resolution"] = 60
Then re-deploy the backtest or live algorithm.
Option B: 📁 Load from External JSON or CSV (for AI optimization)
We can add logic to load a config like this:
json
Copy
Edit
"AAPL": {"lookback": 24, "cycle": 10, "smoothing": 0.35, "resolution": 60},
"MSFT": {"lookback": 30, "cycle": 12, "smoothing": 0.3, "resolution": 30}
You could load it from:
AWS S3
Dropbox
Google Sheets (via connector)
QuantConnect ObjectStore
Would you like me to build this loader?
Option C: 🤖 ChatGPT + Auto Insert
You ask:
“Give me optimized oscillator config for AAPL, MSFT, and NVDA”
And I reply with:
python
Copy
Edit
self.symbol_config = {
"AAPL": {"lookback": 22, "cycle": 9, "smoothing": 0.27, "resolution": 30},
...
You paste it in and re-run the strategy.
✅ Summary
Task How You Do It
Change oscillator levels (e.g., from +1/-1 to +0.8/-0.9) Add thresholds to the symbol_config
dict
Change smoothing or timeframes Edit the config in the script
Scale to 20+ symbols Add tickers to symbol_config — one line each
Automate strategy tuning Use JSON loader or let ChatGPT generate config code
Connect TradingView to QuantConnect ❌ Not needed (QuantConnect has full oscillator
logic now)