Overall Statistics
Total Trades
368
Average Win
1.81%
Average Loss
-0.49%
Compounding Annual Return
14.294%
Drawdown
14.300%
Expectancy
0.545
Net Profit
65.176%
Sharpe Ratio
0.769
Loss Rate
67%
Win Rate
33%
Profit-Loss Ratio
3.69
Alpha
0.102
Beta
-0.014
Annual Standard Deviation
0.132
Annual Variance
0.017
Information Ratio
0.373
Tracking Error
0.265
Treynor Ratio
-7.375
Total Fees
$481.92
namespace QuantConnect 
{   
    public class ForexMovingAvgCross : QCAlgorithm
    {
    	//Create list of currency pairs to be traded
    	List<string> Pairs = new List<string>
        {
        	"AUDUSD",
        	"EURCHF",
        	"EURGBP",
        	"EURJPY",
        	"EURUSD",
        	"GBPUSD",
        	"NZDUSD",
        	"USDCAD",
        	"USDCHF",
        	"USDJPY"
        };
        
        //Prepare a list for holding instances of the SymbolData object.
        List<SymbolData> SymbolData = new List<SymbolData>();
            
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
        	
        	//Override the default fee model with Fxcm's
        	SetBrokerageModel(BrokerageName.FxcmBrokerage);
			
            //Start and End Date range for the backtest:
            SetStartDate(2007, 4, 1);         
            SetEndDate(2010, 12, 31);
            
            //Cash allocation
            SetCash(100000);
            
            //Iterate through the pairs list and prepare data
            foreach (var symbol in Pairs)
            {
            	//add the pair to algorithm
            	AddForex(symbol, Resolution.Hour, Market.FXCM);
            	
            	//prepare the indicators required for the strategy
            	var atr = ATR(symbol, 100, MovingAverageType.Simple, Resolution.Daily);
            	var fastMA = SMA(symbol, 10, Resolution.Daily);
            	var slowMA = SMA(symbol, 100, Resolution.Daily);
            	
            	/*Intialize an object representing the pair to and add 
            	it to the symboldata list */
            	SymbolData.Add(new SymbolData
            	{
            		Symbol = symbol,
            		Atr = atr,
            		FastMA = fastMA,
            		SlowMA = slowMA,
            		Risk = .002m //logic can be subsituted here to set per pair risk metrics
            	});
            }
            
            Schedule.On(DateRules.EveryDay(Pairs[0]), TimeRules.AfterMarketOpen(Pairs[0], 0), () =>
            {
            	ManageTrades();
            });
        }

        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {
        }
        public void ManageTrades()
        {
        	//Iterate through each currency pair
            foreach(var symbolObj in SymbolData)
            {
            	if (symbolObj.Atr == 0m)
            	{
            		continue;
            	}
            	//If the current pair is flat
            	if (!Portfolio[symbolObj.Symbol].Invested)
            	{
            		//Check for long entry criteria
            		if (symbolObj.FastMA >= symbolObj.SlowMA)
            		{
            			MarketOrder(symbolObj.Symbol, symbolObj.AdjustedLotSize(Portfolio));
            		}
            		//Otherwise enter short position
            		else
            		{
            			MarketOrder(symbolObj.Symbol, -symbolObj.AdjustedLotSize(Portfolio));
            		}
            	}
            	//If the portfolio holds a long position
            	else if (Portfolio[symbolObj.Symbol].IsLong)
            	{	
            		//Check for reversal criteria
            		if (symbolObj.FastMA < symbolObj.SlowMA)
            		{
            			//Liquidate and send short order
            			Liquidate(symbolObj.Symbol);
            			MarketOrder(symbolObj.Symbol, -symbolObj.AdjustedLotSize(Portfolio));
            		}
            	}
            	//If the portfolio holds a short position
            	else if (Portfolio[symbolObj.Symbol].IsShort)
        		{
        			//Check for reversal criteria
            		if (symbolObj.FastMA >= symbolObj.SlowMA)
            		{
            			//Liquidate and send buy order
            			Liquidate(symbolObj.Symbol);
            			MarketOrder(symbolObj.Symbol, symbolObj.AdjustedLotSize(Portfolio));
            		}
            	}
            }
        }
    }
    class SymbolData
	{
	    public string Symbol;
        
    	public AverageTrueRange Atr { get; set; }
	    public SimpleMovingAverage FastMA { get; set; }
	    public SimpleMovingAverage SlowMA { get; set; }
	    public decimal Risk { get; set; }

		// Calculate the adjusted lot size based on risk managment criteria
    	public int AdjustedLotSize(SecurityPortfolioManager Portfolio)
    	{
    		//get the current account value
    		var equity = Portfolio.TotalPortfolioValue;
    		//determine the lotsize for the current pair
    		var lotSize = Portfolio.Securities[Symbol].SymbolProperties.LotSize;
    		//obtain the conversion rate for the pair
    		var conversionRate = Portfolio.Securities[Symbol].QuoteCurrency.ConversionRate;
    		var adjustedSize = 10000m;
    		
    		adjustedSize = (Risk * equity)/(Atr * conversionRate);
    		
    		adjustedSize = Math.Floor(adjustedSize/lotSize) * lotSize;
    		
	        return (int)adjustedSize;
	    }
    }
}