Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Calculators/OnlineProfitCalculator.cs @ 15624

Last change on this file since 15624 was 15583, checked in by swagner, 7 years ago

#2640: Updated year of copyrights in license headers

File size: 4.5 KB
RevLine 
[9176]1#region License Information
2/* HeuristicLab
[15583]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[9176]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;
[9744]24using System.Linq;
[9176]25using HeuristicLab.Common;
26
[9743]27namespace HeuristicLab.Problems.DataAnalysis.Trading {
[9176]28  public class OnlineProfitCalculator : IOnlineCalculator {
29
[9938]30    private int position; // currently held position: -1: short, 0: out of market, 1: long
[9744]31    private readonly double transactionCost;
[9938]32    private int count; // only necessary to reset position and total profit on the first data point
33    private double totalProfit;
[9176]34    public double Profit {
[9938]35      get { return totalProfit; }
[9176]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() {
[9938]51      position = 0;
52      count = 0;
53      totalProfit = 0.0;
[9176]54    }
55
56    public void Add(double actualReturn, double signal) {
[9938]57      double profit = 0.0;
58      if (count == 0) {
59        position = (int)signal;
60        profit = 0;
61        count++;
[9176]62      } else {
[9938]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;
[9176]86        }
[9938]87        count++;
[9176]88      }
[9938]89      totalProfit += profit;
[9176]90    }
91    #endregion
92
93    public static double Calculate(IEnumerable<double> returns, IEnumerable<double> signals, double transactionCost, out OnlineCalculatorError errorState) {
[9744]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
[9176]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;
[9744]108
109        double prevTotalProfit = calc.Profit;
110        calc.Add(@return, signal);
111        double curTotalProfit = calc.Profit;
112
113        yield return curTotalProfit - prevTotalProfit;
[9176]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.