/*
 * Copyright (c) 2006-2009 OrangeSignal.com All rights reserved.
 * 
 * これは Apache ライセンス Version 2.0 (以下、このライセンスと記述) に
 * 従っています。このライセンスに準拠する場合以外、このファイルを使用
 * してはなりません。このライセンスのコピーは以下から入手できます。
 * 
 * http://www.apache.org/licenses/LICENSE-2.0.txt
 * 
 * 適用可能な法律がある、あるいは文書によって明記されている場合を除き、
 * このライセンスの下で配布されているソフトウェアは、明示的であるか暗黙の
 * うちであるかを問わず、「保証やあらゆる種類の条件を含んでおらず」、
 * 「あるがまま」の状態で提供されるものとします。
 * このライセンスが適用される特定の許諾と制限については、このライセンス
 * を参照してください。
 */

package jp.sf.orangesignal.trading.stats;

import java.io.Serializable;
import java.util.Map;

/**
 * <p>勝ちトレード及び負けトレードに関するパフォーマンス概要情報の基底クラスを提供します。</p>
 * 
 * @author 杉澤 浩二
 */
public abstract class WinLossSummary implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * <p>デフォルトコンストラクタです。</p>
	 * <p>このコンストラクタはサブクラスを実装する開発者向けに提供しています。</p>
	 */
	protected WinLossSummary() {}

	/**
	 * シンボルとパフォーマンス統計情報のマップと初期資金を指定してこのクラクを構築するコンストラクタです。
	 * 
	 * @param statsMap シンボルとパフォーマンス統計情報のマップ
	 * @param initialCapital 初期資金
	 */
	public WinLossSummary(final Map<String, Stats> statsMap, final double initialCapital) {
		statistics(statsMap, initialCapital);
	}

	/**
	 * <p>指定されたシンボルとパフォーマンス統計情報のマップを解析して、このクラスの統計情報を設定します。</p>
	 * 
	 * @param statsMap シンボルとパフォーマンス統計情報のマップ
	 * @param initialCapital 初期資金
	 */
	protected void statistics(final Map<String, Stats> statsMap, final double initialCapital) {
		this.initialCapital = initialCapital;

		for (final Map.Entry<String, Stats> entry : statsMap.entrySet()) {
			final Stats stats = entry.getValue();
			if (!isStatistics(stats))
				continue;

			this.count++;
			this.trades += stats.getTrades();
			this.winTrades += stats.getWinTrades();
			this.lossTrades += stats.getLossTrades();
			this.netProfit += stats.getNetProfit();
		}
	}

	/**
	 * <p>指定されたパフォーマンス統計情報が、このクラスの統計情報の対象であるかどうかを返します。</p>
	 * 
	 * @param stats パフォーマンス統計情報
	 * @return 指定されたパフォーマンス統計情報が、統計情報の対象である場合は <code>true</code> それ以外の場合は <code>false</code>
	 */
	protected abstract boolean isStatistics(Stats stats);

	// ----------------------------------------------------------------------
	// 資産

	/**
	 * 初期資金を保持します。
	 */
	protected double initialCapital;

	/**
	 * 初期資金を返します。
	 * 
	 * @return 初期資金
	 */
	public double getInitialCapital() { return initialCapital; }

	/**
	 * <p>指定された価格に対しての百分率を返します。</p>
	 * 
	 * @param amount 価格
	 * @return 指定された価格に対しての百分率
	 */
	public double getPercent(final double amount) {
		if (amount == 0.0 || initialCapital == 0.0)
			return 0.0;
		return amount / initialCapital;
	}

	// ----------------------------------------------------------------------
	// 回数/期間

	/**
	 * 回数を保持します。
	 */
	protected int count;

	/**
	 * 回数を返します。
	 * 
	 * @return 対象ポジションの発生回数
	 */
	public int getCount() { return count; }

	/**
	 * <p>回数における指定された値の平均値を返します。</p>
	 * 
	 * @param value 値
	 * @return 平均値
	 */
	public double getAverage(final double value) {
		if (value == 0.0 || count == 0)
			return 0.0;
		return value / count;
	}

	// ----------------------------------------------------------------------

	/**
	 * トレード数を保持します。
	 */
	protected int trades;

	/**
	 * トレード数を返します。
	 * 
	 * @return トレード数
	 */
	public int getTrades() { return trades; }

	/**
	 * <p>トレード数における指定された値の平均値を返します。</p>
	 * 
	 * @param value 値
	 * @return 平均値
	 */
	public double getTradeAverage(final double value) {
		if (value == 0.0 || trades == 0)
			return 0.0;
		return value / trades;
	}

	/**
	 * 勝ちトレード数を保持します。
	 */
	protected int winTrades;

	/**
	 * <p>勝ちトレード数を返します。</p>
	 * 
	 * @return 勝ちトレード数
	 */
	public int getWinTrades() { return winTrades; }

	/**
	 * <p>勝ちトレード率を返します。</p>
	 * 
	 * @return 勝ちトレード率
	 */
	public double getPercentWinTrades() {
		if (winTrades == 0 || getTrades() == 0)
			return 0.0;
		return (double) winTrades / (double) getTrades();
	}

	/**
	 * 負けトレード数を保持します。
	 */
	protected int lossTrades;

	/**
	 * <p>負けトレード数を返します。</p>
	 * 
	 * @return 負けトレード数
	 */
	public int getLossTrades() { return lossTrades; }

	/**
	 * <p>負けトレード率を返します。</p>
	 * <pre>
	 * 負けトレード率＝負けトレード数÷総トレード数
	 * </pre>
	 * 
	 * @return 負けトレード率
	 */
	public double getPercentLossTrades() {
		if (lossTrades == 0 || getTrades() == 0)
			return 0.0;
		return (double) lossTrades / (double) getTrades();
	}

	// ----------------------------------------------------------------------
	// 損益

	/**
	 * 損益を保持します。
	 */
	protected double netProfit;

	/**
	 * 損益を返します。
	 * 
	 * @return 損益
	 */
	public double getNetProfit() { return netProfit; }

	/**
	 * 損益率を返します。
	 * 
	 * @return 損益率
	 */
	public double getPercentNetProfit() { return getPercent(getNetProfit()); }

	/**
	 * 平均損益を返します。
	 * 
	 * @return 平均損益
	 */
	public double getAverageNetProfit() { return getAverage(getNetProfit()); }

	/**
	 * 平均損益率を返します。
	 * 
	 * @return 平均損益率
	 */
	public double getPercentAverageNetProfit() { return getPercent(getAverageNetProfit()); }

}
