Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Calculators/OnlineProfitCalculator.cs @ 13736

Last change on this file since 13736 was 12009, checked in by ascheibe, 10 years ago

#2212 updated copyright year

File size: 4.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26
27namespace HeuristicLab.Problems.DataAnalysis.Trading {
28  public class OnlineProfitCalculator : IOnlineCalculator {
29
30    private int position; // currently held position: -1: short, 0: out of market, 1: long
31    private readonly double transactionCost;
32    private int count; // only necessary to reset position and total profit on the first data point
33    private double totalProfit;
34    public double Profit {
35      get { return totalProfit; }
36    }
37
38    public OnlineProfitCalculator(double transactionCost) {
39      this.transactionCost = transactionCost;
40      Reset();
41    }
42
43    #region IOnlineCalculator Members
44    public OnlineCalculatorError ErrorState {
45      get { return OnlineCalculatorError.None; }
46    }
47    public double Value {
48      get { return Profit; }
49    }
50    public void Reset() {
51      position = 0;
52      count = 0;
53      totalProfit = 0.0;
54    }
55
56    public void Add(double actualReturn, double signal) {
57      double profit = 0.0;
58      if (count == 0) {
59        position = (int)signal;
60        profit = 0;
61        count++;
62      } else {
63        if (position == 0 && signal.IsAlmost(0)) {
64        } else if (position == 0 && signal.IsAlmost(1)) {
65          position = 1;
66          profit = -transactionCost;
67        } else if (position == 0 && signal.IsAlmost(-1)) {
68          position = -1;
69          profit = -transactionCost;
70        } else if (position == 1 && signal.IsAlmost(1)) {
71          profit = actualReturn;
72        } else if (position == 1 && signal.IsAlmost(0)) {
73          profit = actualReturn - transactionCost;
74          position = 0;
75        } else if (position == 1 && signal.IsAlmost(-1)) {
76          profit = actualReturn - transactionCost;
77          position = -1;
78        } else if (position == -1 && signal.IsAlmost(-1)) {
79          profit = -actualReturn;
80        } else if (position == -1 && signal.IsAlmost(0)) {
81          profit = -actualReturn - transactionCost;
82          position = 0;
83        } else if (position == -1 && signal.IsAlmost(1)) {
84          profit = -actualReturn - transactionCost;
85          position = 1;
86        }
87        count++;
88      }
89      totalProfit += profit;
90    }
91    #endregion
92
93    public static double Calculate(IEnumerable<double> returns, IEnumerable<double> signals, double transactionCost, out OnlineCalculatorError errorState) {
94      errorState = OnlineCalculatorError.None;
95      return GetProfits(returns, signals, transactionCost).Sum();
96    }
97
98    public static IEnumerable<double> GetProfits(IEnumerable<double> returns, IEnumerable<double> signals, double transactionCost) {
99      var calc = new OnlineProfitCalculator(transactionCost);
100
101      IEnumerator<double> returnsEnumerator = returns.GetEnumerator();
102      IEnumerator<double> signalsEnumerator = signals.GetEnumerator();
103
104      // always move forward both enumerators (do not use short-circuit evaluation!)
105      while (returnsEnumerator.MoveNext() & signalsEnumerator.MoveNext()) {
106        double signal = signalsEnumerator.Current;
107        double @return = returnsEnumerator.Current;
108
109        double prevTotalProfit = calc.Profit;
110        calc.Add(@return, signal);
111        double curTotalProfit = calc.Profit;
112
113        yield return curTotalProfit - prevTotalProfit;
114      }
115
116      // check if both enumerators are at the end to make sure both enumerations have the same length
117      if (returnsEnumerator.MoveNext() || signalsEnumerator.MoveNext()) {
118        throw new ArgumentException("Number of elements in first and second enumeration doesn't match.");
119      }
120    }
121  }
122}
Note: See TracBrowser for help on using the repository browser.