| Overall Statistics |
|
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 4.083 Tracking Error 0.113 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
# region imports
from AlgorithmImports import *
from datetime import timedelta
import numpy as np
from sklearn.linear_model import LinearRegression
# endregion
class Volumeprofile(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 7, 10)
self.set_end_date(2024, 7, 21)
self.set_cash(100000)
self.future_chains = None
# Set the symbol of the asset we want to trade
future = self.add_future(Futures.Indices.NASDAQ_100_E_MINI, Resolution.Minute)
future.SetFilter(timedelta(0), timedelta(182))
self.symbol = future.Symbol
# Volume Profile indicator settings
self.profile_period = 120 # 2 hours
self.value_area_percentage = 0.4
self.volume_profile = VolumeProfile("Volume Profile", self.profile_period, self.value_area_percentage)
# Rolling window to store past prices
self.past_prices_period = 20
self.past_prices = RollingWindow[TradeBar](self.past_prices_period)
# Long or short position
self.is_long = True
# Consolidate data
self.Consolidate(self.symbol, timedelta(minutes=1), self.on_data_consolidated)
self.register_indicator(self.symbol, self.volume_profile, timedelta(hours = 2))
# Setting stoploss
self.stop_loss_len = 100
self.stop_loss_indicator = self.MIN(self.symbol, self.stop_loss_len, Resolution.MINUTE)
self.lowest_low = 0
self.stop_loss = 0
self.start_stop_loss = False
# Warm up period
self.set_warm_up(timedelta(hours = 2))
# Free portfolio setting
self.settings.free_portfolio_value = 0.3
def on_data_consolidated(self, data: Slice):
# Store the past prices of the future contract
self.past_prices.Add(data)
def on_data(self, data: Slice):
# Check if the strategy warm up period is over and indicators are ready
if self.is_warming_up and not self.volume_profile.is_ready:
return
# Find the future contract
for chain in data.FutureChains:
self.popular_contracts = [contract for contract in chain.value if contract.open_interest > 1000]
if len(self.popular_contracts) == 0:
continue
sorted_bt_o_i_contracts = sorted(self.popular_contracts, key=lambda k: k.open_interest, reverse=True)
self.future_contract = sorted_bt_o_i_contracts[0]
if self.past_prices.is_ready and self.volume_profile.is_ready:
past_prices = [x.Close for x in self.past_prices if x is not None]
slope = self.compute_slope(past_prices)
# Check if price is moving towards the value area
current_price = self.past_prices[0].Close
# Entry
if not self.portfolio.invested:
if (self.volume_profile.value_area_low <= current_price <= self.volume_profile.value_area_high):
# Long condition
if slope < -0.5:
# self.log("Price is moving up towards the value area")
self.set_holdings(self.future_contract.symbol, 1)
self.stop_loss = self.stop_loss_indicator.Current.Value
self.start_stop_loss = True
# self.is_long = True
# elif slope < 0:
# self.log("Price is moving down towards the value area")
# self.set_holdings(self.symbol, -1)
# self.take_profit = self.volume_profile.profile_low
# self.stop_loss = self.volume_profile.poc_price
# self.is_long = False
# Exit
if self.portfolio.invested and self.start_stop_loss:
# Register stop loss and take profit levels
if self.past_prices.IsReady:
if self.past_prices[0].Close > self.past_prices[1].Close:
self.stop_loss += (self.past_prices[0].Close - self.past_prices[1].Close)
# Stop loss
# if data.Close < self.stop_loss or not self.Time.hour in range(9, 16):
if current_price < self.stop_loss:
self.log(f"Stop loss at {current_price}")
self.liquidate(self.future_contract.symbol)
self.start_stop_loss = False
# elif self.portfolio.invested and not self.is_long:
# if current_price <= self.take_profit or current_price >= self.stop_loss:
# self.log("Closing short position")
# self.Liquidate()
# # Plotting the data
# # self.plot("VolumeProfile","vp", self.volume_profile.current.value)
# self.plot("VolumeProfile","profile_high", self.volume_profile.profile_high)
# self.plot("VolumeProfile","profile_low", self.volume_profile.profile_low)
# self.plot("VolumeProfile","poc_price", self.volume_profile.poc_price)
# # self.plot("VolumeProfile","poc_volume", self.volume_profile.poc_volume)
# # self.plot("VolumeProfile","value_area_volume", self.volume_profile.value_area_volume)
# self.plot("VolumeProfile","value_area_high", self.volume_profile.value_area_high)
# self.plot("VolumeProfile","value_area_low", self.volume_profile.value_area_low)
# self.plot("VolumeProfile","current_price", self.past_prices[0].Close)
def compute_slope(self, prices: list) -> float:
# Convert list to numpy array and reshape to 2D for sklearn
prices_array = np.array(prices).reshape(-1, 1)
# Create an array of indices representing time
times = np.array(range(len(prices))).reshape(-1, 1)
# Fit a linear regression model
model = LinearRegression().fit(times, prices_array)
# Return the slope of the regression line
return model.coef_[0][0]
# region imports
from AlgorithmImports import *
from datetime import timedelta
import numpy as np
from sklearn.linear_model import LinearRegression
# endregion
class Volumeprofile(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 1, 1)
self.set_end_date(2024, 6, 1)
self.set_cash(100000)
self.future_chains = None
# Set the symbol of the asset we want to trade
future = self.add_future(Futures.Indices.NASDAQ_100_E_MINI, Resolution.Minute)
future.SetFilter(timedelta(0), timedelta(182))
self.symbol = future.Symbol
# Volume Profile indicator settings
self.profile_period = 120 # 2 hours
self.value_area_percentage = 0.4
self.volume_profile = VolumeProfile("Volume Profile", self.profile_period, self.value_area_percentage)
# Rolling window to store past prices
self.past_prices_period = 20
self.past_prices = RollingWindow[TradeBar](self.past_prices_period)
# Long or short position
self.is_long = True
# Consolidate data
self.Consolidate(self.symbol, timedelta(minutes=1), self.on_data_consolidated)
self.register_indicator(self.symbol, self.volume_profile, timedelta(hours = 2))
# Setting stoploss
self.stop_loss_len = 100
self.stop_loss_indicator = self.MIN(self.symbol, self.stop_loss_len, Resolution.MINUTE)
self.lowest_low = 0
self.stop_loss = 0
self.start_stop_loss = False
# Warm up period
self.set_warm_up(timedelta(days = 2))
# Free portfolio setting
self.settings.free_portfolio_value = 0.3
def on_data_consolidated(self, data: Slice):
# Store the past prices of the future contract
self.past_prices.Add(data)
def on_data(self, data: Slice):
# Check if the strategy warm up period is over and indicators are ready
if self.is_warming_up and not self.volume_profile.is_ready:
return
# Find the future contract
for chain in data.FutureChains:
self.popular_contracts = [contract for contract in chain.value if contract.open_interest > 1000]
if len(self.popular_contracts) == 0:
continue
sorted_bt_o_i_contracts = sorted(self.popular_contracts, key=lambda k: k.open_interest, reverse=True)
self.future_contract = sorted_bt_o_i_contracts[0]
# Log the volume profile `volume_per_price` property
volume_profile_list = [(self.volume_profile.volume_per_price.Keys[i], self.volume_profile.volume_per_price.Values[i]) for i in range(len(self.volume_profile.volume_per_price.Keys))]
self.Debug({volume_profile_list})