/*
 * 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.StatValues;

import com.strategyquant.lib.results.SQOrderList;
import com.strategyquant.lib.results.SQStats;
import com.strategyquant.lib.results.StatValue;
import com.strategyquant.lib.results.StatsConst;
import com.strategyquant.lib.results.StatsTypeCombination;
import com.strategyquant.lib.settings.SQSettings;
import com.strategyquant.lib.utils.SQUtils;

public class ZProbabilityValues extends StatValue {

	@Override
	public String dependsOn() {
		return StatsConst.Z_SCORE;
	}
	    
	@Override
	public void initCompute(SQStats stats, StatsTypeCombination combination, SQOrderList ordersList, SQSettings settings, SQStats statsLong, SQStats statsShort) {
	}
	
	@Override
	public void endCompute(SQStats stats, StatsTypeCombination combination, SQOrderList ordersList, SQSettings settings, SQStats statsLong, SQStats statsShort) throws Exception {
		double zScore = stats.getDouble(StatsConst.Z_SCORE);
		double zProbability;
		
		if(zScore<=-10) {
			zProbability = 99.9;
		} else {
			zProbability = 100d*calculateProbabilityFromZ(zScore);
		}
		
		stats.set(StatsConst.Z_PROBABILITY, SQUtils.round2(zProbability));
	}

    private double calculateProbabilityFromZ(double zScore) throws Exception {
        if (Math.abs(zScore) > 6f) {
        	return 0;
        } else {
            return (1 - poz((zScore)));
        }
    }
    
    private double poz(double z) {
        double y, x, w;
        
        if (z == 0f) {
            x = 0f;
        } else {
            y = 0.5 * Math.abs(z);
            if (y > (6 * 0.5)) {
                x = 1.0;
            } else if (y < 1.0) {
                w = y * y;
                x = ((((((((0.000124818987 * w
                         - 0.001075204047) * w + 0.005198775019) * w
                         - 0.019198292004) * w + 0.059054035642) * w
                         - 0.151968751364) * w + 0.319152932694) * w
                         - 0.531923007300) * w + 0.797884560593) * y * 2.0;
            } else {
                y -= 2.0;
                x = (((((((((((((-0.000045255659 * y
                               + 0.000152529290) * y - 0.000019538132) * y
                               - 0.000676904986) * y + 0.001390604284) * y
                               - 0.000794620820) * y - 0.002034254874) * y
                               + 0.006549791214) * y - 0.010557625006) * y
                               + 0.011630447319) * y - 0.009279453341) * y
                               + 0.005353579108) * y - 0.002141268741) * y
                               + 0.000535310849) * y + 0.999936657524;
            }
        }
        return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5);
    }

}