| 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 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Selection;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
public class UglySkyBlueScorpion : QCAlgorithm
{
Symbol _equitySymbol;
Symbol _optionContract;
Symbol _futureContract;
public override void Initialize()
{
SetStartDate(2024, 7, 20);
SetCash(100000);
SetBrokerageModel(BrokerageName.TradeStation);
_equitySymbol = AddEquity("AAPL").Symbol;
var option = AddOption(_equitySymbol);
option.SetFilter(u => u.Strikes(-2, +2).Expiration(0, 60));
var future = AddFuture(Futures.Indices.SP500EMini);
future.SetFilter(TimeSpan.Zero, TimeSpan.FromDays(182));
}
int _testCase = 0;
int _openOrdersTimeout;
public override void OnData(Slice slice)
{
if (!SetFutureContract(slice))
{
Debug($"{Time}: Waiting for future contract to be set...");
return;
}
if (!SetOptionContract(slice))
{
Debug($"{Time}: Waiting for option contract to be set...");
return;
}
foreach (var symbol in new [] { _equitySymbol, _optionContract, _futureContract})
{
if (Securities[symbol].Price == 0)
{
Debug($"{Time}: Waiting for {symbol} to have price...");
return;
}
}
// TRADE
if (_testCase == 0)
{
if (Portfolio.Invested)
{
Debug($"{Time}: Liquidating so we start from scratch");
Liquidate();
return;
}
if (Transactions.GetOpenOrders().Count > 0)
{
Debug($"{Time}: Cancelling open orders so we start from scratch");
Transactions.CancelOpenOrders();
return;
}
Debug($"{Time}: Sending market orders");
foreach (var symbol in new [] { _equitySymbol, _optionContract, _futureContract})
{
MarketOrder(symbol, 1);
}
_testCase = 1;
}
else if (_testCase == 1)
{
Debug($"{Time}: Sending limit orders");
foreach (var symbol in new [] { _equitySymbol, _optionContract, _futureContract})
{
// bellow market price so triggers asap
LimitOrder(symbol, -1, GetOrderPrice(symbol, aboveTheMarket: false));
}
_testCase = 2;
}
else if (_testCase == 2)
{
if (Portfolio.Invested)
{
// should be filled
Debug($"{Time}: Liquidating so we start from scratch");
Liquidate();
return;
}
Debug($"{Time}: Sending StopMarketOrder orders");
foreach (var symbol in new [] { _equitySymbol, _optionContract, _futureContract})
{
// Buy Stop order is always placed above the current market price
StopMarketOrder(symbol, 1, GetOrderPrice(symbol, aboveTheMarket: true));
}
_testCase = 3;
}
else if (_testCase == 3)
{
if (Transactions.GetOpenOrders().Count > 0)
{
if (_openOrdersTimeout++ > 5)
{
Debug($"{Time}: Tiemout waiting for orders to fill, cancelling");
Transactions.CancelOpenOrders();
return;
}
else
{
Debug($"{Time}: Has open orders, waiting...");
return;
}
}
Debug($"{Time}: Sending StopLimitOrder orders");
foreach (var symbol in new [] { _equitySymbol, _optionContract, _futureContract})
{
var aboveTheMarket = GetOrderPrice(symbol, aboveTheMarket: false);
StopLimitOrder(symbol, -1, aboveTheMarket, aboveTheMarket);
}
_testCase = 4;
Debug($"{Time}: The END!");
}
}
// get a valid price above or below market, for options respect 0.05m increment
private decimal GetOrderPrice(Symbol symbol, bool aboveTheMarket)
{
var assetPrice = Securities[symbol].Price;
if (aboveTheMarket)
{
if (symbol.SecurityType.IsOption() && assetPrice >= 2.95m)
{
return (assetPrice + 0.05m).DiscretelyRoundBy(0.05m);
}
assetPrice = assetPrice + Math.Min(assetPrice * 0.001m, 0.25m);
}
else
{
if (symbol.SecurityType.IsOption() && assetPrice >= 2.95m)
{
return (assetPrice - 0.05m).DiscretelyRoundBy(0.05m);
}
assetPrice = assetPrice - Math.Min(assetPrice * 0.001m, 0.25m);
}
return assetPrice;
}
private bool SetFutureContract(Slice slice)
{
if (_futureContract == null)
{
foreach(var chain in slice.FutureChains.Values)
{
var contract = ( from futuresContract in chain.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Time.Date.AddDays(90)
select futuresContract
).FirstOrDefault();
_futureContract = contract.Symbol;
}
}
return _futureContract != null;
}
private bool SetOptionContract(Slice slice)
{
if (_optionContract == null)
{
foreach(var optionChain in slice.OptionChains.Values)
{
var atmContract = optionChain
.OrderByDescending(x => x.Expiry)
.ThenBy(x => Math.Abs(optionChain.Underlying.Price - x.Strike))
.ThenByDescending(x => x.Right)
.FirstOrDefault();
_optionContract = atmContract.Symbol;
}
}
return _optionContract != null;
}
}
}