| Overall Statistics |
|
Total Trades 552 Average Win 2.15% Average Loss -1.81% Compounding Annual Return 8.748% Drawdown 15.700% Expectancy 0.252 Net Profit 223.831% Sharpe Ratio 0.734 Loss Rate 43% Win Rate 57% Profit-Loss Ratio 1.19 Alpha 0.074 Beta 0.002 Annual Standard Deviation 0.1 Annual Variance 0.01 Information Ratio 0.135 Tracking Error 0.21 Treynor Ratio 44.089 Total Fees $1331.16 |
namespace QuantConnect
{
/*
* John Ehlers' MESA
* (programmed by Jean-Paul van Brakel)
*/
public class BasicTemplateAlgorithm : QCAlgorithm
{
public string _ticker = "SPY"; // which stock ticker
public static int MESA_length = 9; // indicator length
public static decimal _limit = 0.85M; // threshold for anti-trend liquidation
private readonly RollingWindow<double> Prices = new RollingWindow<double>(MESA_length);
private Chart plotter;
decimal _oldprice = 100000;
decimal _price;
decimal _oldsine;
decimal _sine;
decimal _lead;
int _dir = 0;
public override void Initialize()
{
//Start and End Date range for the backtest:
SetStartDate(2000, 1, 1);
SetEndDate(2014, 1, 1);
SetCash(25000);
AddSecurity(SecurityType.Equity, _ticker, Resolution.Daily);
plotter = new Chart("MESA", ChartType.Overlay);
plotter.AddSeries(new Series("MESA sine", SeriesType.Line));
plotter.AddSeries(new Series("MESA lead", SeriesType.Line));
AddChart(plotter);
}
public void OnData(TradeBars data)
{
Prices.Add((double)(data[_ticker].High + data[_ticker].Low)/2);
_price = data[_ticker].Close;
if (!Prices.IsReady) return;
// MESA
// *********************************************************************************************************
double realPart = 0;
double imagPart = 0;
for (int i = 0; i < MESA_length; i++) {
double temp = Prices[i];
realPart = realPart + temp*Math.Cos(2*Math.PI*i/MESA_length);
imagPart = imagPart + temp*Math.Sin(2*Math.PI*i/MESA_length);
}
double phase1 = 0;
if (Math.Abs(realPart) > 0.001) {
phase1 = Math.Atan(imagPart/realPart);
} else {
phase1 = (Math.PI / 2*Math.Sign(imagPart));
}
double phase2 = 0;
if (realPart < 0) {
phase2 = phase1 + Math.PI;
} else {
phase2 = phase1;
}
double phase = 0;
if (phase2 < 0) {
phase = phase2 + 2*Math.PI;
} else if (phase2 > 2*Math.PI) {
phase = phase2 - 2*Math.PI;
} else {
phase = phase2;
}
_oldsine = _sine;
_sine = (decimal) Math.Cos(phase);
_lead = (decimal) Math.Cos(phase+Math.PI/4);
int _old_dir = _dir;
if (_lead < _sine && _dir != -1) {
_dir = -1;
} else if (_lead > _sine && _dir != 1) {
_dir = 1;
}
// *********************************************************************************************************
// Update chart
Plot("MESA", "MESA sine", _sine+90);
Plot("MESA", "MESA lead", _lead+90);
// Order logic / (simple) risk management
decimal pps = ((_price - _oldprice)/_oldprice)*100;
if (pps >= 4.5M || pps < -2.0M || _dir != _old_dir || // if P/L crosses boundaries
(_sine < _limit && _sine > _oldsine && _dir == -1) || // if direction is wrong
(_sine > _limit && _sine < _oldsine && _dir == 1)) { // if direction is wrong
// End position
Liquidate(_ticker);
}
if (!Portfolio.HoldStock) {
int quantity = (int)Math.Floor(Portfolio.Cash / data[_ticker].Close);
if (_dir != _old_dir) {
if (quantity > 0)
Order(_ticker, _dir*quantity);
_oldprice = _price;
}
}
}
}
}