| Overall Statistics |
|
Total Trades 22 Average Win 0.49% Average Loss -0.67% Compounding Annual Return -99.787% Drawdown 5.600% Expectancy -0.686 Net Profit -4.950% Sharpe Ratio -26.237 Loss Rate 82% Win Rate 18% Profit-Loss Ratio 0.73 Alpha -3.182 Beta 0.946 Annual Standard Deviation 0.121 Annual Variance 0.015 Information Ratio -26.323 Tracking Error 0.121 Treynor Ratio -3.354 Total Fees $245.36 |
using QuantConnect.Brokerages;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
namespace QuantConnect.Algorithm.CSharp
{
public class TestForexAlgorithm : QCAlgorithm
{
private string currencyPair = "EURUSD";
private Resolution algoResolution = Resolution.Minute;
private decimal minPriceVariation;
private decimal leverage = 15m;
private decimal orderSize = 0m;
private decimal initCashSize = 25000;
private int pipTarget = 10;
private int pipStopLoss = 15;
private decimal price;
private decimal targetPrice;
private decimal stopLossPrice;
private int longShortDirection;
private Dictionary<Symbol, Delay> _rsi = new Dictionary<Symbol, Delay>();
private Dictionary<Symbol, Stochastic> _sto = new Dictionary<Symbol, Stochastic>();
// first set of criteria
private int stoOverbought = 80;
private int stoOversold = 20;
private int rsiOverbought = 70;
private int rsiOversold = 30;
// second set of criteria
private Delay rsi;
private Stochastic sto;
private QuoteBarConsolidator fifteenMinuteConsolidator;
public override void Initialize()
{
// TODO: Determine a way to exit the algo in case that during init it is found that the account carries equities
if (Portfolio.HoldStock)
{
Log("The Portfolio is not empty!");
}
SetStartDate(2013, 1, 7);
SetEndDate(2013, 1, 9);
SetCash(initCashSize);
AddForex(currencyPair, algoResolution, Market.FXCM);
fifteenMinuteConsolidator = new QuoteBarConsolidator(TimeSpan.FromMinutes(15));
var realrsi = new RelativeStrengthIndex("RSI_" + currencyPair, 14, MovingAverageType.Simple);
rsi = new Delay(1).Of(realrsi);
sto = new Stochastic("STO_" + currencyPair, 14, 5, 3);
_rsi.Add(currencyPair, rsi);
_sto.Add(currencyPair, sto);
RegisterIndicator(currencyPair, rsi, fifteenMinuteConsolidator);
RegisterIndicator(currencyPair, sto, fifteenMinuteConsolidator);
SetWarmup(20);
SubscriptionManager.AddConsolidator(currencyPair, fifteenMinuteConsolidator);
fifteenMinuteConsolidator.DataConsolidated += FifteenMinuteHandler;
minPriceVariation = Securities[currencyPair].SymbolProperties.MinimumPriceVariation * 10;
Log("Minimum Price Variation: " + minPriceVariation);
SetBrokerageModel(BrokerageName.FxcmBrokerage);
}
private void FifteenMinuteHandler(object sender, QuoteBar bar)
{
if (_rsi.Values.All(x => x.IsReady) && _sto.Values.All(x => x.IsReady))
{
Debug("DelayedRsiValue:" + _rsi[currencyPair].Current);
Debug("StocValue:" + _sto[currencyPair].Current);
price = Securities[currencyPair].Price;
if (!Portfolio.HoldStock)
{
scanForEntry();
}
else
{
scanForExit(price);
}
}
}
public void OnData(QuoteBars data)
{
if (rsi.IsReady)
{
var tmpRsi = rsi;
tmpRsi.Update(Time , price);
tmpRsi.Reset();
}
}
private void scanForEntry()
{
if (_rsi[currencyPair] < rsiOversold && _sto[currencyPair].StochK < stoOversold)
{
longShortDirection = 1;
orderSize = leverage * longShortDirection;
SetHoldings(currencyPair, orderSize);
calculateTargetAndStopLoss(pipTarget, pipStopLoss, Portfolio[currencyPair].AveragePrice, longShortDirection);
return;
}
else if (_rsi[currencyPair] > rsiOverbought && _sto[currencyPair].StochK > stoOverbought)
{
longShortDirection = -1;
orderSize = leverage * longShortDirection;
SetHoldings(currencyPair, orderSize);
calculateTargetAndStopLoss(pipTarget, pipStopLoss, Portfolio[currencyPair].AveragePrice, longShortDirection);
return;
}
}
private void calculateTargetAndStopLoss(decimal _pipTarget, decimal _pipStopLoss, decimal _averagePrice, int _longShortDirection)
{
targetPrice = _averagePrice + _pipTarget * minPriceVariation * _longShortDirection;
stopLossPrice = _averagePrice + _pipStopLoss * minPriceVariation * _longShortDirection;
}
private void scanForExit(decimal currentPrice)
{
if (reachedProfitTarget(currentPrice))
{
Liquidate();
Log("|Profit");
}
else if (reachedStopLossTarget(currentPrice))
{
Liquidate();
Log("|Loss");
}
}
private bool reachedProfitTarget(decimal currentPrice)
{
if (longShortDirection == 1)
{
if (currentPrice >= targetPrice)
{
return true;
}
else
{
return false;
}
}
else if (longShortDirection == -1)
{
if (currentPrice <= targetPrice)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
private bool reachedStopLossTarget(decimal currentPrice)
{
if (longShortDirection == 1)
{
if (stopLossPrice >= currentPrice)
{
return true;
}
else
{
return false;
}
}
else if (longShortDirection == -1)
{
if (stopLossPrice <= currentPrice)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
}