| Overall Statistics |
|
Total Trades 69 Average Win 0.31% Average Loss -0.08% Compounding Annual Return 71.214% Drawdown 1.100% Expectancy 0.119 Net Profit 1.434% Sharpe Ratio 11.022 Probabilistic Sharpe Ratio 88.790% Loss Rate 76% Win Rate 24% Profit-Loss Ratio 3.70 Alpha 0.537 Beta -0.053 Annual Standard Deviation 0.047 Annual Variance 0.002 Information Ratio 0.773 Tracking Error 0.112 Treynor Ratio -9.688 Total Fees $269.46 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Parameters;
using QuantConnect.Brokerages;
using QuantConnect.Indicators;
using QuantConnect.Securities;
namespace QuantConnect.Algorithm.CSharp
{
public enum VWAPState
{
Long,
Short,
Empty
};
public class VWAPAlgorithm : QCAlgorithm
{
private readonly string _ticker = "XOM";
[Parameter("cash")]
private readonly int _cash;
private Resolution _resolution = Resolution.Minute;
private AlphaModel _alphaModel;
public override void Initialize()
{
Chart _plotter1 = new Chart("Chart 1", ChartType.Overlay);
_plotter1.AddSeries(new Series("Price", SeriesType.Line, "$", Color.Green));
_plotter1.AddSeries(new Series("VWAP", SeriesType.Line, "%", Color.Red));
// _plotter1.AddSeries(new Series("MOMP", SeriesType.Line, "%", Color.Yellow));
_plotter1.AddSeries(new Series("Long", SeriesType.Scatter, "", Color.Blue, ScatterMarkerSymbol.Square));
_plotter1.AddSeries(new Series("Short", SeriesType.Scatter, "", Color.Pink, ScatterMarkerSymbol.Square));
AddChart(_plotter1);
//Chart _plotter2 = new Chart("Chart 2", ChartType.Overlay);
//_plotter2.AddSeries(new Series("RSI", SeriesType.Line, "%", Color.Red));
//AddChart(_plotter2);
SetStartDate(2020, 1, 1);
SetEndDate(2020, 1, 10);
SetCash(_cash);
SetUniverseSelection(
new ManualUniverseSelectionModel(
QuantConnect.Symbol.Create(_ticker, SecurityType.Equity, Market.USA)
)
);
UniverseSettings.Resolution = _resolution;
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
_alphaModel = new VWAPAlphaModel(_resolution);
AddAlpha(_alphaModel);
SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel());
SetExecution(new ImmediateExecutionModel());
SetRiskManagement(new LiquidatePositionOnDrawdawn());
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
}
}
public class VWAPAlphaModel : AlphaModel
{
private Resolution _resolution;
private Security _security;
private IntradayVwap _vwap;
private RelativeStrengthIndex _rsi;
private MomentumPercent _momp;
private RollingWindow<decimal> _priceRw = new RollingWindow<decimal>(2);
private QCAlgorithm _algorithm;
public VWAPAlphaModel(Resolution resolution)
{
_resolution = resolution;
}
public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
{
_algorithm = algorithm;
_security = changes.AddedSecurities.First();
_vwap = algorithm.VWAP(_security.Symbol);
_rsi = algorithm.RSI(_security.Symbol, 14, MovingAverageType.Simple, _resolution);
_momp = algorithm.MOMP(_security.Symbol, 14, _resolution);
}
public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data)
{
algorithm.Plot("Chart 1", "Price", _security.Price);
algorithm.Plot("Chart 1", "VWAP", _vwap);
algorithm.Plot("Chart 2", "MOMP", _momp * 100);
algorithm.Plot("Chart 2", "RSI", _rsi);
_priceRw.Add(_security.Price);
if (!data.ContainsKey(_security.Symbol) || !_vwap.IsReady || !_priceRw.IsReady)
{
return Enumerable.Empty<Insight>();
}
if (State() != VWAPState.Long && _priceRw[0] > _vwap && _priceRw[1] <= _vwap)
{
return Insight.Group(Insight.Price(_security.Symbol, Expiry.EndOfDay, InsightDirection.Up));
}
if (State() != VWAPState.Short && _priceRw[0] < _vwap && _priceRw[1] >= _vwap)
{
return Insight.Group(Insight.Price(_security.Symbol, Expiry.EndOfDay, InsightDirection.Down));
}
return Enumerable.Empty<Insight>();
}
private VWAPState State()
{
decimal quantity = _algorithm.Portfolio[_security.Symbol].Quantity;
if (quantity > 0)
{
return VWAPState.Long;
}
if (quantity < 0)
{
return VWAPState.Short;
}
return VWAPState.Empty;
}
}
public class LiquidatePositionOnDrawdawn : RiskManagementModel
{
public LiquidatePositionOnDrawdawn()
{
}
public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
{
foreach (var kvp in algorithm.Securities)
{
Security security = kvp.Value;
if (security.Invested)
{
// Liquidate holdings on end of trading session
if (algorithm.Time.Hour == 15 && algorithm.Time.Minute == 59)
{
yield return new PortfolioTarget(security.Symbol, 0);
}
// Liquidate holdings on drawdawn
//if (security.Holdings.Quantity == _previousQuantity)
//{
//}
}
//_previousQuantity = security.Holdings.Quantity;
continue;
}
}
}
}