Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/24/13 12:51:02 (11 years ago)
Author:
gkronber
Message:

#1508 refactoring: removed unused classes, unified calculation of profits and signals, implemented profit-evaluator.

Location:
branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4
Files:
1 added
2 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Calculators/OnlineProfitCalculator.cs

    r9743 r9744  
    2222using System;
    2323using System.Collections.Generic;
     24using System.Linq;
    2425using HeuristicLab.Common;
    2526
     
    2829
    2930    private int p;
    30     private double transactionCost;
     31    private readonly double transactionCost;
    3132    private int c;
    3233    private double sum;
     
    6364        } else if (p == 0 && signal.IsAlmost(1)) {
    6465          p = 1;
     66          iterationReturn = -transactionCost;
    6567        } else if (p == 0 && signal.IsAlmost(-1)) {
    6668          p = -1;
     69          iterationReturn = -transactionCost;
    6770        } else if (p == 1 && signal.IsAlmost(1)) {
    6871          iterationReturn = actualReturn;
     
    8992
    9093    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
    91101      IEnumerator<double> returnsEnumerator = returns.GetEnumerator();
    92102      IEnumerator<double> signalsEnumerator = signals.GetEnumerator();
    93       OnlineProfitCalculator calculator = new OnlineProfitCalculator(transactionCost);
    94103
    95104      // always move forward both enumerators (do not use short-circuit evaluation!)
     
    97106        double signal = signalsEnumerator.Current;
    98107        double @return = returnsEnumerator.Current;
    99         calculator.Add(@return, signal);
     108
     109        double prevTotalProfit = calc.Profit;
     110        calc.Add(@return, signal);
     111        double curTotalProfit = calc.Profit;
     112
     113        yield return curTotalProfit - prevTotalProfit;
    100114      }
    101115
     
    103117      if (returnsEnumerator.MoveNext() || signalsEnumerator.MoveNext()) {
    104118        throw new ArgumentException("Number of elements in first and second enumeration doesn't match.");
    105       } else {
    106         errorState = calculator.ErrorState;
    107         return calculator.Profit;
    108119      }
    109120    }
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Calculators/OnlineSharpeRatioCalculator.cs

    r9743 r9744  
    2222using System;
    2323using System.Collections.Generic;
    24 using HeuristicLab.Common;
    2524
    2625namespace HeuristicLab.Problems.DataAnalysis.Trading {
    2726  public class OnlineSharpeRatioCalculator : IOnlineCalculator {
    2827
    29     private int p;
    30     private double transactionCost;
    31     private int c;
    3228    private OnlineMeanAndVarianceCalculator meanAndVarianceCalculator;
     29    private OnlineProfitCalculator profitCalculator;
     30
    3331    public double SharpeRatio {
    3432      get {
     
    4038
    4139    public OnlineSharpeRatioCalculator(double transactionCost) {
    42       this.transactionCost = transactionCost;
    4340      this.meanAndVarianceCalculator = new OnlineMeanAndVarianceCalculator();
     41      this.profitCalculator = new OnlineProfitCalculator(transactionCost);
    4442      Reset();
    4543    }
     
    4846    public OnlineCalculatorError ErrorState {
    4947      get {
    50         return meanAndVarianceCalculator.MeanErrorState | meanAndVarianceCalculator.VarianceErrorState;
     48        return meanAndVarianceCalculator.MeanErrorState | meanAndVarianceCalculator.VarianceErrorState | profitCalculator.ErrorState;
    5149      }
    5250    }
     
    5553    }
    5654    public void Reset() {
    57       p = 0;
    58       c = 0;
     55      profitCalculator.Reset();
    5956      meanAndVarianceCalculator.Reset();
    6057    }
    6158
    6259    public void Add(double actualReturn, double signal) {
    63       double iterationReturn = 0.0;
    64       if (c == 0) {
    65         p = (int)signal;
    66         iterationReturn = 0;
    67         c++;
    68       } else {
    69         if (p == 0 && signal.IsAlmost(0)) {
    70         } else if (p == 0 && signal.IsAlmost(1)) {
    71           p = 1;
    72         } else if (p == 0 && signal.IsAlmost(-1)) {
    73           p = -1;
    74         } else if (p == 1 && signal.IsAlmost(1)) {
    75           iterationReturn = actualReturn;
    76         } else if (p == 1 && signal.IsAlmost(0)) {
    77           iterationReturn = actualReturn - transactionCost;
    78           p = 0;
    79         } else if (p == 1 && signal.IsAlmost(-1)) {
    80           iterationReturn = actualReturn - transactionCost;
    81           p = -1;
    82         } else if (p == -1 && signal.IsAlmost(-1)) {
    83           iterationReturn = -actualReturn;
    84         } else if (p == -1 && signal.IsAlmost(0)) {
    85           iterationReturn = -actualReturn - transactionCost;
    86           p = 0;
    87         } else if (p == -1 && signal.IsAlmost(1)) {
    88           iterationReturn = -actualReturn - transactionCost;
    89           p = 1;
    90         }
    91         c++;
    92       }
    93       meanAndVarianceCalculator.Add(iterationReturn);
     60      double prevTotalProfit = profitCalculator.Profit;
     61      profitCalculator.Add(actualReturn, signal);
     62      double curTotalProfit = profitCalculator.Profit;
     63
     64      meanAndVarianceCalculator.Add(curTotalProfit - prevTotalProfit);
    9465    }
    9566    #endregion
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/HeuristicLab.Problems.DataAnalysis.Trading-3.4.csproj

    r9743 r9744  
    161161    <Compile Include="Calculators\OnlineProfitCalculator.cs" />
    162162    <Compile Include="HeuristicLabProblemsDataAnalysisTradingPlugin.cs" />
    163     <Compile Include="Interfaces\ITradingEnsembleModel.cs" />
    164163    <Compile Include="Interfaces\ITradingModel.cs" />
    165164    <Compile Include="Interfaces\ITradingProblem.cs" />
     
    171170    <Compile Include="Symbolic\Interfaces\ISymbolicTradingSingleObjectiveEvaluator.cs" />
    172171    <Compile Include="Symbolic\Interfaces\ISymbolicTradingSolution.cs" />
     172    <Compile Include="Symbolic\SingleObjective\ProfitEvaluator.cs" />
    173173    <Compile Include="Symbolic\SingleObjective\SymbolicTradingSingleObjectiveEvaluator.cs" />
    174174    <Compile Include="Symbolic\SingleObjective\SymbolicTradingSingleObjectiveProblem.cs" />
     
    184184      <DependentUpon>SymbolicTradingSolutionView.cs</DependentUpon>
    185185    </Compile>
    186     <Compile Include="TradingEnsembleModel.cs" />
    187186    <Compile Include="TradingProblem.cs" />
    188187    <Compile Include="TradingProblemData.cs" />
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SingleObjective/SymbolicTradingSingleObjectiveSharpeRatioEvaluator.cs

    r9743 r9744  
    6868
    6969    private static IEnumerable<double> GetSignals(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, Dataset dataset, IEnumerable<int> rows) {
    70       return from x in interpreter.GetSymbolicExpressionTreeValues(solution, dataset, rows)
    71              select x > 0.5 ? 1.0 : x < 0.5 ? -1.0 : 0.0;
     70      return SymbolicTradingModel.GetSignals(interpreter.GetSymbolicExpressionTreeValues(solution, dataset, rows));
    7271    }
    7372
    7473    public override double Evaluate(IExecutionContext context, ISymbolicExpressionTree tree, ITradingProblemData problemData, IEnumerable<int> rows) {
    7574      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context;
    76 
    7775      double sharpRatio = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, problemData, rows);
    78 
    7976      SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null;
    80 
    8177      return sharpRatio;
    8278    }
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SymbolicTradingModel.cs

    r9743 r9744  
    4949      ISymbolicDataAnalysisExpressionTreeInterpreter interpreter = Interpreter;
    5050      ISymbolicExpressionTree tree = SymbolicExpressionTree;
    51       return from x in interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows)
    52              select x > 0.66 ? 1.0 : x < 0.33 ? -1.0 : 0.0;
     51      return GetSignals(interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows));
     52    }
     53
     54    // Transforms an enumerable of real values to an enumerable of trading signals (buy(1) / hold(0) / sell(-1))
     55    public static IEnumerable<double> GetSignals(IEnumerable<double> xs) {
     56      // two iterations over xs
     57      // 1) determine min / max to calculate the mid-range value
     58      // 2) range is split into three thirds
     59      double max = double.NegativeInfinity;
     60      double min = double.PositiveInfinity;
     61      foreach (var x in xs) {
     62        if (x > max) max = x;
     63        if (x < min) min = x;
     64      }
     65      if (double.IsInfinity(max) || double.IsNaN(max) || double.IsInfinity(min) || double.IsNaN(min))
     66        return xs.Select(x => 0.0);
     67
     68      double range = (max - min);
     69      double midRange = range / 2.0 + min;
     70      double offset = range / 6.0;
     71      return from x in xs
     72             select x > midRange + offset ? 1.0 : x < midRange - offset ? -1.0 : 0.0;
    5373    }
    5474  }
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Symbolic/SymbolicTradingSolution.cs

    r9743 r9744  
    3232  /// </summary>
    3333  [StorableClass]
    34   [Item(Name = "SymbolicTradingSolution", Description = "Represents a symbolic trading solution (model + data) and attributes of the solution like accuracy and complexity.")]
     34  [Item(Name = "SymbolicTradingSolution",
     35    Description =
     36      "Represents a symbolic trading solution (model + data) and attributes of the solution like accuracy and complexity."
     37    )]
    3538  public sealed class SymbolicTradingSolution : TradingSolution, ISymbolicTradingSolution {
    3639    private const string ModelLengthResultName = "Model Length";
     
    4144      set { base.Model = value; }
    4245    }
     46
    4347    ISymbolicDataAnalysisModel ISymbolicDataAnalysisSolution.Model {
    4448      get { return (ISymbolicDataAnalysisModel)base.Model; }
    4549    }
     50
    4651    public int ModelLength {
    4752      get { return ((IntValue)this[ModelLengthResultName].Value).Value; }
     
    5560
    5661    [StorableConstructor]
    57     private SymbolicTradingSolution(bool deserializing) : base(deserializing) { }
     62    private SymbolicTradingSolution(bool deserializing)
     63      : base(deserializing) {
     64    }
     65
    5866    private SymbolicTradingSolution(SymbolicTradingSolution original, Cloner cloner)
    5967      : base(original, cloner) {
    6068    }
     69
    6170    public SymbolicTradingSolution(ISymbolicTradingModel model, ITradingProblemData problemData)
    6271      : base(model, problemData) {
     
    7584    }
    7685
    77     private new void RecalculateResults() {
     86    protected override void RecalculateResults() {
     87      base.RecalculateResults();
     88      CalculateResults();
     89    }
     90
     91    private void CalculateResults() {
    7892      ModelLength = Model.SymbolicExpressionTree.Length;
    7993      ModelDepth = Model.SymbolicExpressionTree.Depth;
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/TradingProblemData.cs

    r9743 r9744  
    3737
    3838    #region default data
    39     private static double[,] audInUsd = new double[,] {
     39    private static double[,] audInUsdDiff = new double[,] {
    4040    { 0.0000},
    4141    { 0.0003},
     
    15891589
    15901590    static TradingProblemData() {
    1591       defaultDataset = new Dataset(new string[] { "AUD" }, audInUsd);
     1591      defaultDataset = new Dataset(new string[] { "AUD" }, audInUsdDiff);
    15921592      defaultDataset.Name = "AUD in USD";
    15931593      defaultDataset.Description = "Price of Australian dollar in US dollar.";
     
    16301630      : base(dataset, allowedInputVariables) {
    16311631      var variables = InputVariables.Select(x => x.AsReadOnly()).ToList();
    1632       Parameters.Add(new ConstrainedValueParameter<StringValue>(PriceVariableParameterName, new ItemSet<StringValue>(variables), variables.Where(x => x.Value == targetVariable).First()));
     1632      Parameters.Add(new ConstrainedValueParameter<StringValue>(PriceVariableParameterName, new ItemSet<StringValue>(variables), variables.First(x => x.Value == targetVariable)));
    16331633      Parameters.Add(new FixedValueParameter<DoubleValue>(TransactionCostsParameterName, "The absolute cost of on buy/sell transaction (assumed to be constant and independent of transaction volume)", new DoubleValue(0.0002)));
    16341634      RegisterParameterEvents();
     
    16461646      OnChanged();
    16471647    }
    1648 
    1649    
    1650 
    1651 
    1652     //#region Import from file
    1653     //public static TradingProblemData ImportFromFile(string fileName) {
    1654     //  TableFileParser csvFileParser = new TableFileParser();
    1655     //  csvFileParser.Parse(fileName);
    1656 
    1657     //  Dataset dataset = new Dataset(csvFileParser.VariableNames, csvFileParser.Values);
    1658     //  dataset.Name = Path.GetFileName(fileName);
    1659 
    1660     //  TradingProblemData problemData = new TradingProblemData(dataset, dataset.VariableNames.Skip(1), dataset.VariableNames.First());
    1661     //  problemData.Name = "Data imported from " + Path.GetFileName(fileName);
    1662     //  return problemData;
    1663     //}
    1664     //#endregion
    16651648  }
    16661649}
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/TradingSolution.cs

    r9743 r9744  
    7878      Add(new Result(TrainingProfitResultName, "Profit of the model on the training partition", new DoubleValue()));
    7979      Add(new Result(TestProfitResultName, "Profit of the model on the test partition", new DoubleValue()));
    80 
    81       RecalculateResults();
    8280    }
    8381
     
    9492
    9593    protected override void RecalculateResults() {
     94      CalculateTradingResults();
     95    }
     96
     97    protected void CalculateTradingResults() {
    9698      double[] trainingSignals = TrainingSignals.ToArray(); // cache values
    9799      IEnumerable<double> trainingReturns = ProblemData.Dataset.GetDoubleValues(ProblemData.PriceVariable, ProblemData.TrainingIndices);
  • branches/HeuristicLab.Problems.DataAnalysis.Trading/HeuristicLab.Problems.DataAnalysis.Trading/3.4/Views/TradingSolutionLineChartView.cs

    r9743 r9744  
    2525using System.Windows.Forms;
    2626using System.Windows.Forms.DataVisualization.Charting;
    27 using HeuristicLab.Common;
    2827using HeuristicLab.MainForm;
    29 using HeuristicLab.MainForm.WindowsForms;
    3028using HeuristicLab.Problems.DataAnalysis.Views;
    3129
     
    6159      this.chart.Series.Clear();
    6260      if (Content != null) {
    63         //this.chart.Series.Add(PRICEVARIABLE_SERIES_NAME);
    64         //this.chart.Series[PRICEVARIABLE_SERIES_NAME].LegendText = Content.ProblemData.PriceVariable;
    65         //this.chart.Series[PRICEVARIABLE_SERIES_NAME].ChartType = SeriesChartType.FastLine;
    66         //this.chart.Series[PRICEVARIABLE_SERIES_NAME].Points.DataBindY(Content.ProblemData.Dataset.GetVariableValues(Content.ProblemData.PriceVariable));
    67 
    68 
    6961        this.chart.Series.Add(SIGNALS_SERIES_NAME);
    7062        this.chart.Series[SIGNALS_SERIES_NAME].LegendText = SIGNALS_SERIES_NAME;
     
    8072        this.chart.Series[PRICEVARIABLE_SERIES_NAME].Tag = Content;
    8173
    82         IEnumerable<double> profit = GetProfits(Content.ProblemData.Dataset.GetDoubleValues(Content.ProblemData.PriceVariable), Content.Signals, Content.ProblemData.TransactionCosts);
     74        IEnumerable<double> profit = OnlineProfitCalculator.GetProfits(Content.ProblemData.Dataset.GetDoubleValues(Content.ProblemData.PriceVariable), Content.Signals, Content.ProblemData.TransactionCosts);
    8375        IEnumerable<double> accumulatedProfits = GetAccumulatedPrices(profit);
    8476        this.chart.Series.Add(ASSET_SERIES_NAME);
     
    8981
    9082        this.UpdateStripLines();
    91 
    92         // UpdateCursorInterval();
    93       }
    94     }
    95 
    96     private IEnumerable<double> GetProfits(IEnumerable<double> returns, IEnumerable<double> signals, double transactionCost) {
    97       int p = (int)signals.First();
    98       yield return 0.0;
    99       foreach (var signalReturn in returns.Skip(1).Zip(signals.Skip(1), (r, s) => new { Return = r, Signal = s })) {
    100         double iterationReturn = 0;
    101         double signal = signalReturn.Signal;
    102         double actualReturn = signalReturn.Return;
    103         if (p == 0 && signal.IsAlmost(0)) {
    104         } else if (p == 0 && signal.IsAlmost(1)) {
    105           iterationReturn = 0;
    106           p = 1;
    107         } else if (p == 0 && signal.IsAlmost(-1)) {
    108           iterationReturn = 0;
    109           p = -1;
    110         } else if (p == 1 && signal.IsAlmost(1)) {
    111           iterationReturn = actualReturn;
    112         } else if (p == 1 && signal.IsAlmost(0)) {
    113           iterationReturn = actualReturn - transactionCost;
    114           p = 0;
    115         } else if (p == 1 && signal.IsAlmost(-1)) {
    116           iterationReturn = actualReturn - transactionCost;
    117           p = -1;
    118         } else if (p == -1 && signal.IsAlmost(-1)) {
    119           iterationReturn = -actualReturn;
    120         } else if (p == -1 && signal.IsAlmost(0)) {
    121           iterationReturn = -actualReturn - transactionCost;
    122           p = 0;
    123         } else if (p == -1 && signal.IsAlmost(1)) {
    124           iterationReturn = -actualReturn - transactionCost;
    125           p = 1;
    126         }
    127         yield return iterationReturn;
    12883      }
    12984    }
     
    13691      }
    13792    }
    138 
    139     //private void UpdateCursorInterval() {
    140     //  var estimatedValues = this.chart.Series[SIGNALS_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
    141     //  var targetValues = this.chart.Series[PRICEVARIABLE_SERIES_NAME].Points.Select(x => x.YValues[0]).DefaultIfEmpty(1.0);
    142     //  double estimatedValuesRange = estimatedValues.Max() - estimatedValues.Min();
    143     //  double targetValuesRange = targetValues.Max() - targetValues.Min();
    144     //  double interestingValuesRange = Math.Min(Math.Max(targetValuesRange, 1.0), Math.Max(estimatedValuesRange, 1.0));
    145     //  double digits = (int)Math.Log10(interestingValuesRange) - 3;
    146     //  double yZoomInterval = Math.Max(Math.Pow(10, digits), 10E-5);
    147     //  this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
    148     //}
    14993
    15094    #region events
Note: See TracChangeset for help on using the changeset viewer.