/*
 * Copyright (c) 2015, StrategyQuant - All rights reserved.
 *
 * Code in this file was made in a good faith that it is correct and does what it should. 
 * If you found a bug in this code OR you have an improvement suggestion OR you want to include 
 * your own code snippet into our standard library please contact us at:
 * http://tasks.strategyquant.com/projects/snippets/
 *
 * This code can be used only within StrategyQuant products. 
 * Every owner of valid (free, trial or commercial) license of any StrategyQuant product 
 * is allowed to freely use, copy, modify or make derivative work of this code without limitations,
 * to be used in all StrategyQuant products and share his/her modifications or derivative work 
 * with the StrategyQuant community.
 *  
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES 
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *  
 */
package com.strategyquant.extend.EquityControl;

import com.strategyquant.lib.language.L;
import com.strategyquant.lib.snippets.Trade;
import com.strategyquant.lib.snippets.EquityControlSim.EquityControl;

public class MovingAverage extends EquityControl {

	public MovingAverage() {
		setName(L.t("Moving Average"));
		
		addIntParameter("Period", L.t("Period"), 20, 2, 1000, 1);
	}
	
	/**
	 * computes control line that will be drawn on chart and used to compute new equity
	 * 
	 * If you need to check value of something for debugging purpose you can use function logToFile(fileName, text).
	 * Example: logToFile("debug_file", trades[1].openTime)
	 *
	 *           
	 * Trade structure:
	 *   .openTime - opening time of trade in seconds from 1.1.1970
	 *   .balanceOnOpen - actual account balance on trade open
	 *   .pl - trade resulting Profit/Loss in %
	 *   .size - trade size            
	 *                         
	 * @param originalTrades - list of original trades
	 * @return - return an array of double values that represent computed equity control line 
	 * that will be used to control the equity.
	 */
	@Override
	public double[] computeBalanceControlLine(Trade[] originalTrades) throws Exception {
		double[] controlLine = new double[originalTrades.length];
		
		int period = getIntParameterValue("Period");
		
		// computes Simple Moving Average of trades equity (balance)
		for(int i=0; i<originalTrades.length; i++) {
			if( i<= period) {
				controlLine[i] = VALUE_UNDEFINED;
			} else {
				controlLine[i] = computeSMA(originalTrades, i, period);
			}
		}
		
		return controlLine;
	}
	
    /**
     * Function computes simple moving average. This is only an example, 
     * you can compute the control line any way you want.
     */       
	private double computeSMA(Trade[] originalTrades, int shift, int period) {
		double avg = 0; 

		for(int i = shift-1; i > shift - 1 - period; i--) {
			avg += originalTrades[i].balanceOnOpen;
		}

		return avg / (period);
	}

	/**
	 * Function receives list of trades sorted by open time and computed control line.
	 * It computes new size for every trade.
	 * 
	 * The standard approach is that is balance at open of trade is bigger than control line then take the trade (keep size unchanged)
	 * otherwise skip the trade (set trade size = 0).           
	 * You can also modify the original trade size to use more advanced money management scheme - 
	 *  for example if balance is below equity don't skip the trade, but trade with only half of the size.  
	 * 
	 * If you need to check value of something for debugging purpose you can use function logToFile(fileName, text).
	 * Example: logToFile("debug_file", trades[1].openTime)
	 * 
	 *                    
	 * Trade structure:
	 *   .openTime - opening time of trade in seconds from 1.1.1970
	 *   .balanceOnOpen - actual account balance on trade open
	 *   .pl - trade resulting Profit/Loss in %
	 *   .size - trade size
	 *                    
	 * @param trades - list of original trades. Each trade has account balance on open accessible through .balanceOnOpen property
	 * @param balanceControlLine - controlline computed using function computeControlLine()    
	 */	
    @Override
	public void computeNewTradeSizes(Trade[] trades, double[] balanceControlLine) {
   
        for(int i=0; i<trades.length; i++) {
            if(balanceControlLine[i] == VALUE_UNDEFINED || trades[i].balanceOnOpen >= balanceControlLine[i]) {
			      // control line is either undefined
			      // or equity is above control line
			      // do nothing, take the trade without any change      
			   } else {
				   // equity is below control line, miss the trade
				   trades[i].size = 0f;
			   }
        }
	 }
}