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; } } } }