using System.Net;
namespace QuantConnect.Algorithm.CSharp
{
public class ParticleTransdimensionalCoreWave : QCAlgorithm
{
private QuantConnect.Securities.Future.Future future;
private List<ContractData> contractDataList;
private int lookback = 60;
private double takeProfit = 0.001;
private double stopLoss = 0.001;
public override void Initialize()
{
SetStartDate(2019, 8, 1); //Set Start Date
SetEndDate(2019, 10, 1); //Set Start Date
SetCash(100000); //Set Strategy Cash
future = AddFuture(Futures.Energies.CrudeOilWTI, Resolution.Minute); //or https://www.quantconnect.com/lean/documentation/topic26533.html
future.SetFilter(TimeSpan.FromDays(0), TimeSpan.FromDays(182));
contractDataList = new List<ContractData>();
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
var order = Transactions.GetOrderById(orderEvent.OrderId);
if (orderEvent.Status == OrderStatus.Filled)
{
var symbol = orderEvent.Symbol;
var fillQuantity = orderEvent.FillQuantity;
var fillPrice = orderEvent.FillPrice;
Debug(string.Format("Open {0} Position on {1}", symbol, fillPrice));
//order.Update(new UpdateOrderFields
//{
// we could change the quantity, but need to specify it
//Quantity =
// StopPrice = fillPrice * (decimal)(1 + takeProfit),
// LimitPrice = fillPrice * (decimal)(1 - stopLoss)
//});
if (order.Type == OrderType.Limit || order.Type == OrderType.StopLimit)
{
Transactions.CancelOpenOrders(symbol);
}
if (order.Type == OrderType.Market)
{
Debug($"{order}");
return;
}
}
}
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// Slice object keyed by symbol containing the stock data
public override void OnData(Slice data)
{
if (!Portfolio.Invested)
{
// In OnData(Slice slice)
FuturesChain chain;
// Explore the future contract chain
if (data.FuturesChains.TryGetValue(future.Symbol, out chain))
{
var underlying = chain.Underlying;
foreach (var contract in chain.Contracts)
{
var sym = contract.Value.Symbol;
if (contractDataList.Count() < 1 || !contractDataList.Any(d => d.Symbol == sym))
{
contractDataList.Add(new ContractData(contract.Value.Symbol, lookback, this));
}
}
}
foreach (ContractData contract in contractDataList)
{
if (contract.IsReady)
{
decimal wilrValue = contract.GetWilliamsRange();
Debug(string.Format("williams range: {0}", wilrValue));
decimal fastSto = contract.GetFastStochastic();
Debug(string.Format("fast STO: {0}", fastSto));
if (contract.IsBuySignal())
{
double close = (double)Securities[contract.Symbol].Close;
var stopPrice = close * 0.099; // Trigger stop limit when price falls 1%.
var limitPrice = close * 1.001; // Sell equal or better than 1% > close.
var stopLimitTicket = StopLimitOrder(contract.Symbol, 10, (decimal)stopPrice, (decimal)limitPrice);
}
else if (contract.IsSellSignal())
{
}
}
}
}
}
public decimal GetFutureStorageData(string url)
{
var json = new WebClient().DownloadString(url);
return 0;
}
}
public class ContractData
{
private WilliamsPercentR wilr;
private Stochastic sto;
public string Symbol;
public ContractData(string symbol, int lookback, QCAlgorithm algo)
{
this.Symbol = symbol;
this.wilr = algo.WILR(symbol, lookback, Resolution.Minute);
this.sto = algo.STO(symbol, lookback, Resolution.Minute);
}
public bool IsReady { get { return wilr.IsReady && sto.IsReady; } }
public decimal GetWilliamsRange()
{
if (!wilr.IsReady)
return decimal.MaxValue;
return wilr.Current.Value;
}
public decimal GetFastStochastic()
{
if (!sto.IsReady)
return decimal.MaxValue;
return sto.FastStoch;
}
public bool IsBuySignal()
{
if (!this.IsReady)
return false;
decimal wpr = GetWilliamsRange();
decimal sto = GetFastStochastic();
return wpr < -80 && sto < 20;
}
public bool IsSellSignal()
{
if (!this.IsReady)
return false;
decimal wpr = GetWilliamsRange();
decimal sto = GetFastStochastic();
return wpr > -20 && sto > 80;
}
}
}