コード例 #1
0
ファイル: TraderGen.cs プロジェクト: heimanhon/researchwork
    public static ConstructGen<double> DoScaleWeights(ConstructGen<double> wts_, TraderArgs args_, Func<DateTime,double> getVolTargetForDate_)
    {
      if (wts_.ColumnHeadings == null)
        wts_.ColumnHeadings = args_.Products.Select(x => x.Name).ToArray();

      var logReturns = args_.AllProductPrices(fillInGapsWithPrevious_: true).ToLogReturns(
        args_.Products.Select(x => x.Convention).ToArray());

      var scaledWts = new ConstructGen<double>(wts_.ColumnHeadings);

      foreach (var date in wts_.Dates)
      {
        var wtArr = wts_.GetValues(date);

        for (int i = 0; i < wtArr.Length; ++i)
          if (double.IsInfinity(wtArr[i]))
            wtArr[i] = 0d;

        int indexOfDate = logReturns.FindIndexOfEffectiveDateOnDate(date);

        indexOfDate = (indexOfDate < 252) ? 252 : indexOfDate - 1; // note offset

        var subValues = logReturns.GetSubValues(logReturns.Dates[indexOfDate - 251], logReturns.Dates[indexOfDate]);

        var covArr = SI.Data.FXHistCovar.MatCovar(subValues.ToArray());

        var cov = new CovarianceItem(covArr);

        scaledWts.SetValues(date, cov.ScaleSeries(wtArr, getVolTargetForDate_(date)));
      }

      return scaledWts;
    }
コード例 #2
0
ファイル: TraderGen.cs プロジェクト: heimanhon/researchwork
    protected override ReturnsEval.DataSeriesEvaluator doPnl(TraderArgs args_, ConstructGen<double> wts_)
    {
      var priceReturns =
        args_.AllProductPrices(fillInGapsWithPrevious_: true)
          .ToReturns(args_.Products.Select(x => x.Convention).ToArray());


      var stratReturns = new ConstructGen<double>(priceReturns.ColumnHeadings);

      double[] appliedWeights = null;

      for (int i = 0; i < priceReturns.Dates.Count; ++i)
      {
        var date = priceReturns.Dates[i];

        var priceReturnsArr = priceReturns.GetValues(date);

        if (appliedWeights != null)
        {
          for (int j = 0; j < priceReturnsArr.Length; ++j)
            stratReturns.SetValue(date, j, appliedWeights[j]*priceReturnsArr[j]);
        }

        if (wts_.Dates.Contains(date))
        {
          appliedWeights = wts_.GetValues(date);
        }
      }

      var eval = new ReturnsEval.DataSeriesEvaluator("Gen pnl from weights", ReturnsEval.DataSeriesType.Returns);
      eval.AddInnerSeries(stratReturns.Dates.ToArray(), stratReturns.ToArray(), stratReturns.ColumnHeadings);

      return eval;
    }
コード例 #3
0
ファイル: TraderFX.cs プロジェクト: heimanhon/researchwork
    public override double[] GetContToVar(double[] wts_, DateTime date_, TraderArgs args_)
    {
      CovarianceItem covar = null;
      DateTime d = date_;

      covar = Singleton<CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(d);

      double[] expWeights = new double[covar.ComponentIds.Count];
      int[] indices = new int[wts_.Length];

      for (int i = 0; i < args_.Products.Count; ++i)
      {
        indices[i] = covar.ComponentIds.IndexOf(((ProductFX)args_.Products[i]).CoreProduct.ID);
        expWeights[indices[i]]=wts_[i];
      }

      double [] contToVar = covar.GetContToVar(expWeights,args_.ScaleUsingDiagMatrix);

      // reshape into length of input products...

      double[] ret = new double[wts_.Length];

      for (int i = 0; i < wts_.Length; ++i)
        ret[i] = contToVar[indices[i]];

      return ret;

    }
コード例 #4
0
ファイル: TraderFX.cs プロジェクト: heimanhon/researchwork
    protected override SI.ReturnsEval.DataSeriesEvaluator doPnl(TraderArgs args_, ConstructGen<double> wts_)
    {
      ConstructGen<double> allCcys = new ConstructGen<double>(Singleton<FXIDs>.Instance.ColumnHeadings);

      for (int i = 0; i < args_.Products.Count; ++i)
      {
        ProductFX prod = (ProductFX)args_.Products[i];
        allCcys.SetColumnValues(prod.CoreProduct.ArrayIndex, wts_.Dates.ToArray(), wts_.GetColumnValues(i));
      }

      var result = ReturnsFromFXWeights.DoIt_DailyWeights(allCcys);
      var eval = new ReturnsEval.DataSeriesEvaluator("FX pnl", ReturnsEval.DataSeriesType.Returns);

      if (args_.WtIndicators.Any())
        eval.Name = string.Format("FX : {0}", args_.WtIndicators[0].ToString());
      
      eval.AddInnerSeries(result.CombinedPnl.Dates.ToArray(), result.CombinedPnl.ToArray(), result.CombinedPnl.ColumnHeadings);

      return eval;
    }
コード例 #5
0
ファイル: TraderFX.cs プロジェクト: heimanhon/researchwork
    public static ConstructGen<double> DoScaleWeights(ConstructGen<double> weights_, double targetVol_, TraderArgs args_)
    {
      //Singleton<Data.FXHistCovar>.Instance.Ensure(weights_.Dates.ToArray(),63);

      ConstructGen<double> ret = new ConstructGen<double>(weights_.ArrayLength);
      ret.ColumnHeadings = weights_.ColumnHeadings;

      foreach (DateTime date in weights_.Dates)
      {
        DateTime d = date;
        CovarianceItem covar = null;

        switch (args_.VolTypeForScaling)
        {
          case VolType.covar:

            covar = Singleton<SI.Data.CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(d);
            //if (covar == null)
            //{
            //  DateTime prevTradingDate = MyCalendar.PrevTradeDate(date, "LNB");
            //  covar = Singleton<Data.FXHistCovar>.Instance[prevTradingDate, 252];
            //}
            break;

          //case Technicals.VolType.hist:
          //  covar = Singleton<Data.FXHistCovar>.Instance[d, args_.HistCovWindowLength];
          //  break;

          default:
            throw new Exception("voltype not implemented");
        }

        // extract and scale weights
        double[] weighted = weightFX(weights_.GetValues(date), covar, args_, targetVol_);

        ret.SetValues(date, weighted);
      }

      return ret;
    }
コード例 #6
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    private void generateRawResults(TraderArgs args_)
    {
      m_resultsWts.Clear();
      m_resultsFilter.Clear();

      foreach (ProductBase product in args_.Products)
      {
        if (args_.WtIndicators.Count > 0)
        {
          var list = new List<DatedDataCollectionGen<double>>();

          foreach (IndicatorBase indic in args_.WtIndicators)
          {
            list.Add(indic.GenerateWeightSeries(product, args_.WtsMinDate));
          }

          m_resultsWts[product] = list;
        }

        // now not trending signals...

        if (args_.FilterIndicators.Count > 0)
        {
          var list = new List<DatedDataCollectionGen<double>>();

          foreach (IndicatorBase indic in args_.FilterIndicators)
          {
            list.Add(indic.GenerateWeightSeries(product,args_.WtsMinDate));
          }

          m_resultsFilter[product] = list;
        }
      }

      m_trendExistResult.Clear();

      if (args_.TrendExistenceIndic != null)
      {
        foreach (ProductBase product in args_.Products)
        {
          m_trendExistResult[product] = args_.TrendExistenceIndic.GenerateWeightSeries(product,args_.WtsMinDate);
        }
      }
    }
コード例 #7
0
ファイル: TraderFX.cs プロジェクト: heimanhon/researchwork
    public static double[] weightFX(double[] input_, CovarianceItem covar_, TraderArgs args_,double targetVol_)
    {
      double[] scaleThis = new double[covar_.ComponentIds.Count];
      int[] indices = new int[input_.Length];

      for (int i = 0; i < args_.Products.Count; ++i)
      {
        indices[i] = covar_.ComponentIds.IndexOf(((ProductFX)args_.Products[i]).CoreProduct.ID);
        scaleThis[indices[i]] = input_[i];
      }

      double[] scaled = covar_.ScaleSeries(scaleThis, targetVol_,args_.ScaleUsingDiagMatrix);

      // contrains weights?

      if (args_.WtConstraints != null && args_.WtConstraints.Enabled)
      {
        bool cont = true;
        int iterationCount = 0;
        double tolerance = 0.05; // 5% tolerance on constraint
        int iterationMax = 100;

        while (cont && iterationCount < iterationMax)
        {
          cont = false;
          double upperLimit = args_.WtConstraints.UpperConstraint + Math.Abs(args_.WtConstraints.UpperConstraint * tolerance);
          double lowerLimit = args_.WtConstraints.LowerConstraint - Math.Abs(args_.WtConstraints.LowerConstraint * tolerance);

          for (int i = 0; i < scaled.Length; ++i)
          {
            if (scaled[i] < lowerLimit)
            {
              scaled[i] = args_.WtConstraints.LowerConstraint;
            }

            if (scaled[i] > upperLimit)
            {
              scaled[i] = args_.WtConstraints.UpperConstraint;
            }
          }

          if (args_.WtConstraints.ReScale)
          {
            scaled = covar_.ScaleSeries(scaled, targetVol_);
            cont = true;
          }

          ++iterationCount;
        }
      }

      // reshape into length of input products...

      double[] ret = new double[input_.Length];

      for (int i = 0; i < input_.Length; ++i)
        ret[i] = scaled[indices[i]];

      return ret;
    }
コード例 #8
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public ReturnsEval.DataSeriesEvaluator Trade(TraderArgs args_)
    {
      var c = GetWeights(args_);

      return doPnl(args_, c);
    }
コード例 #9
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    private DateTime findStartDate(TraderArgs args_)
    {
      DateTime ret = DateTime.MaxValue;

      if (args_.WtsMinDate >= DateTime.Today)
        return args_.WtsMinDate;

      foreach (ProductBase product in m_resultsWts.Keys)
      {
        foreach (DatedDataCollectionGen<double> dd in m_resultsWts[product])
          if (dd!=null && dd.Length>0 && dd.Dates[0] < ret)
            ret = dd.Dates[0];

        if(m_resultsFilter.Count>0)
          foreach (DatedDataCollectionGen<double> dd in m_resultsFilter[product])
            if (dd.Dates[0] > ret)
              ret = dd.Dates[0];
      }

      if (args_.RebalFrequency == RebalFreq.Weekly || args_.RebalFrequency == RebalFreq.BiWeekly)
        while (ret.DayOfWeek != args_.DayOfWeek)
          ret = ret.AddDays(1.0);

      if (args_.RebalFrequency == RebalFreq.Monthly)
        while (ret.Day != args_.MonthlyDayStart)
          ret = ret.AddDays(1.0);

      while (ret.DayOfWeek == DayOfWeek.Saturday || ret.DayOfWeek == DayOfWeek.Sunday)
        ret = ret.AddDays(1.0);

      if (args_.RebalFrequency == RebalFreq.ParticularDate)
        ret = args_.ParticularDate;
      //  while (ret.Day != 4 || ret.DayOfWeek==DayOfWeek.Saturday || ret.DayOfWeek==DayOfWeek.Sunday )
      //    ret = ret.AddDays(1.0);

      return ret;
    }
コード例 #10
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public static List<DateTime> GetRebalDates(TraderArgs args_, DateTime startDate)
    {
      if (args_.RebalDates != null)
        return args_.RebalDates;

      List<DateTime> ret = GenerateRebalDates(args_.RebalFrequency, startDate);

      args_.RebalDates = ret;

      return ret;
    }
コード例 #11
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public static void processToTrigger(ConstructGen<double> wts_, TraderArgs args_, Trader trader_)
    {
      if (wts_.Dates.Count == 0)
        return;

      if (args_.TriggerArgs == null)
        return;

      List<int> datesIndicesToRemove=new List<int>();
      List<int> varContTopIndices = new List<int>();
      List<int> topWtPos = new List<int>();
      double[] before = wts_.GetValues(wts_.Dates[0]);
      double[] varContBefore = (args_.TriggerArgs.DoVarFlipsTrigger) ? trader_.GetContToVar(before, wts_.Dates[0], args_) : null;
      
      if (args_.TriggerArgs.DoVarFlipsTrigger)
        getTopVarIndicies(varContTopIndices, varContBefore, args_.TriggerArgs.VarFlipsTrigger.ConsiderTopVarNumber);
      if (args_.TriggerArgs.DoTopInSizeTrigger)
        getTopPosSizeIndicies(topWtPos, before, args_.TriggerArgs.TopInSizeTrigger.ConsiderTopInSizeNumber);

      List<DateTime> removeTheseDates = new List<DateTime>();
      int daysSinceRebal = 0;

      List<DateTime> includeTheseDates = new List<DateTime>();
      if (args_.TriggerArgs.AlwayRebalFrequencyEnabled)
      {
        // get the dates of rebal the rebalfrequency implies
        includeTheseDates = GenerateRebalDates(args_.TriggerArgs.AlwaysRebalFrequency, wts_.Dates[0]);
      }

      for (int i = 1; i < wts_.Dates.Count; ++i)
      {
        double[] wtsToday = wts_.GetValues(wts_.Dates[i]);
        bool remove=true;

        ++daysSinceRebal;

        // have we exceeded the maximum number of specified days without a rebal?
        if (remove && args_.TriggerArgs.MaxDaysWithoutRebalEnabled && args_.TriggerArgs.MaxDaysWithoutRebal <= daysSinceRebal)
        {
          remove = false;
        }

        // do we want to always rebal on a particular day of the week
        if (remove && args_.TriggerArgs.AlwaysRebalOnDayOfWeekEnabled && args_.TriggerArgs.AlwayRebalOnThisDayOfWeek == wts_.Dates[i].DayOfWeek)
        {
          remove = false;
        }

        // is the date in the list of dates that we always want to maintain
        if (remove && includeTheseDates.Contains(wts_.Dates[i]))
        {
          remove = false;
        }

        // positions that have changed signs must be greater than NUM_CHANGE_FREQ in order for the day to be kept

        if (remove && (args_.TriggerArgs.ChangeSignEnabled || args_.TriggerArgs.ChangeSignOnProportionEnabled))
        {
          int countChanged = 0;
          for (int j = 0; j < wts_.ArrayLength; ++j)
          {
            // change sign in position means keep
            if (Statistics.AreSameSign(before[j], wtsToday[j]) == false)
              ++countChanged;
          }

          int changeOnThisNumber = int.MaxValue;

          // if have decided to change on number of positions that have changed sign...
          if (args_.TriggerArgs.ChangeSignEnabled)
            changeOnThisNumber = Math.Min(changeOnThisNumber, args_.TriggerArgs.MinNumberOfItemsToChange);

          // if have decided to change on proportion of tradeable products to change sign
          if (args_.TriggerArgs.ChangeSignOnProportionEnabled)
          {
            int validCount = numValidProductsOnDate(wts_.Dates[i], args_);

            int numProp = Convert.ToInt32(Convert.ToDouble(validCount) * args_.TriggerArgs.ChangeSignOnThisProportion);

            changeOnThisNumber = Math.Min(changeOnThisNumber, numProp);
          }

          if (countChanged >= changeOnThisNumber)
            remove = false;
        }

        // proportion of portfolio turnover

        if (remove && args_.TriggerArgs.TurnoverEnabled)
        {
          double sumOfTurnover = 0.0;
          double sumOfPositions = 0.0;

          for (int j = 0; j < wts_.ArrayLength; ++j)
          {
            sumOfTurnover += Math.Abs(wtsToday[j] - (before[j]));
            sumOfPositions += Math.Abs(before[j]);
          }

          double propChanged = sumOfTurnover / sumOfPositions;

          if (propChanged >= args_.TriggerArgs.TurnoverThreshold/* TAG:MA32DaysMin && daysSinceRebal>1*/)
            remove = false;
        }

        // trade the flipped positions but don't re-scale everything else

        if (remove==false &&
          args_.TriggerArgs.DontTopLevelScaleIntraWeek == true &&
          args_.TriggerArgs.AlwaysRebalOnDayOfWeekEnabled && args_.TriggerArgs.AlwayRebalOnThisDayOfWeek != wts_.Dates[i].DayOfWeek)
        {
          double[] newArray = new double[before.Length];

          for (int j = 0; j < wts_.ArrayLength; ++j)
          {
            if (Statistics.AreSameSign(before[j], wtsToday[j]))
              newArray[j] = before[j];
            else
              newArray[j] = wtsToday[j];
          }

          wts_.SetValues(wts_.Dates[i], newArray);
          wtsToday = newArray;
        }

        // var flips
        if (remove &&
          args_.TriggerArgs.DoVarFlipsTrigger)
        {
          int numFlipped = 0;

          foreach (int index in varContTopIndices)
            if (Statistics.AreSameSign(before[index], wtsToday[index]) == false)
              ++numFlipped;

          if (numFlipped >= args_.TriggerArgs.VarFlipsTrigger.NumFlipsTrigger)
            remove = false;
        }

        // top in size flips
        if (remove &&
          args_.TriggerArgs.DoTopInSizeTrigger)
        {
          int numFlipped = 0;

          foreach (int index in topWtPos)
            if (Statistics.AreSameSign(before[index], wtsToday[index]) == false)
              ++numFlipped;

          if (numFlipped >= args_.TriggerArgs.TopInSizeTrigger.NumFlipsTrigger)
            remove = false;
        }

        if (remove)
        {
          removeTheseDates.Add(wts_.Dates[i]);
          ++daysSinceRebal;
        }
        else
        {
          before = wtsToday;
          //varContBefore = (trader_ == null || args_.TriggerArgs.VarFlipsTrigger == null || args_.TriggerArgs.VarFlipsTrigger.Enabled == false) ? null : trader_.GetContToVar(before, wts_.Dates[i], args_);
          daysSinceRebal = 0;
          if (args_.TriggerArgs.DoVarFlipsTrigger)
          {
            varContBefore = trader_.GetContToVar(before, wts_.Dates[i], args_);
            getTopVarIndicies(varContTopIndices, varContBefore, args_.TriggerArgs.VarFlipsTrigger.ConsiderTopVarNumber);
          }

          if (args_.TriggerArgs.DoTopInSizeTrigger)
            getTopPosSizeIndicies(topWtPos, before, args_.TriggerArgs.TopInSizeTrigger.ConsiderTopInSizeNumber);
        }
      }

      foreach (DateTime date in removeTheseDates)
        wts_.RemoveValues(date);
    }
コード例 #12
0
ファイル: TraderGen.cs プロジェクト: heimanhon/researchwork
 public static ConstructGen<double> DoScaleWeights(ConstructGen<double> wts_, double targetVol_, TraderArgs args_)
 {
   return DoScaleWeights(wts_, args_, x => targetVol_);
 }
コード例 #13
0
ファイル: RVOLOpt.cs プロジェクト: heimanhon/researchwork
    public static RVOlOptResult GetBackTestWeights(RVolOptArgs optArgs_)
    {
      TraderArgs args = new TraderArgs();

      Array.ForEach(Singleton<FXIDs>.Instance.ToArray(), x => args.Products.Add(ProductFX.GetCached(x)));

      args.RebalFrequency = optArgs_.Freq;
      args.DayOfWeek = DayOfWeek.Tuesday;
      args.ParticularDate = optArgs_.ParticularRebalDate;

      bool doNeg = false;

      List<DateTime> dates;
      if (optArgs_.Freq == RebalFreq.ParticularDate)
        dates = Trader.GenerateRebalDates(args.RebalFrequency, args.ParticularDate);
      else
        dates = Trader.GetRebalDates(args, MyCalendar.NextDayOfWeek(SI.Data.DataConstants.DATA_START, DayOfWeek.Tuesday));

      //ConstructGen<double> carryCon = Singleton<FXCarry>.Instance.GetAnnualizedCarry(MyCalendar.PrevWeekDay(dates[0].AddDays(-10d)), DateTime.Today, 5, false);
      var tranCosts = Singleton<FXTransactionCosts>.Instance.GetData(MyCalendar.PrevWeekDay(dates[0].AddDays(-10d)), DateTime.Today, false);
      var dxyScores = Singleton<DXYScore_21>.Instance.Scores;
      var vixScores = Singleton<VIXScore_21>.Instance.Scores;

      IList<string> exclude = new List<string>();
      {
        if (optArgs_.CcysToExclude != null)
          foreach (string s in optArgs_.CcysToExclude.ToUpper().Trim().Split(','))
            exclude.Add(s);
      }

      // set up scores
      switch (optArgs_.SwitchExpReturn)
      {
        case SwitchSignType.None:
          doNeg = false;
          break;
        case SwitchSignType.AlwaysNegative:
          doNeg = true;
          break;
        case SwitchSignType.DXY21:
          dxyScores = Singleton<DXYScore_21>.Instance.Scores;
          break;
        //case SwitchSignType.CustomDXY21:
        //  dxyScores = Singleton<QC.Common.CurrencyUniverseScore_21>.Instance.Scores;
        //  break;
        //case SwitchSignType.DXY_EMEA21:
        //  dxyScores = Singleton<QC.Common.CurrencyEMScore_21>.Instance.Scores;
        //  break;
        //case SwitchSignType.DXY_LATAM21:
        //  dxyScores = Singleton<QC.Common.CurrencyLATAMScore_21>.Instance.Scores;
        //  break;
        //case SwitchSignType.DXY_NJA21:
        //  dxyScores = Singleton<QC.Common.CurrencyNJAScore_21>.Instance.Scores;
        //  break;
        //case SwitchSignType.DXY_G1021:
        //  dxyScores = Singleton<QC.Common.CurrencyG10Score_21>.Instance.Scores;
        //  break;
        //case SwitchSignType.COTMonWts:
        //  {
        //    ConstructGen<double> cotWts = Backtests.getWE(Strat.COT1Mon).Key;
        //    dxyScores = cotWts.SumRows();
        //    dxyScores = dxyScores.MultiplyBy(-1d);
        //  }
        //  break;
        default:
          throw new Exception(string.Format("Need to code options for {0}", optArgs_.SwitchExpReturn.ToString()));
      }


      Logger.Info(string.Format("Switching threshold on scores is {0}", optArgs_.SwitchThreshold.ToString()), typeof(RVOLOpt));

      List<DateTime> triggerDates = new List<DateTime>();

      // do we want to look for trigger every day?
      if (optArgs_.SwitchDailyTrigger && !double.IsNaN(optArgs_.SwitchThreshold))
      {
        for (int i = 1 + Math.Abs(optArgs_.SwitchDayOffset); i < dxyScores.Length; ++i)
        {
          if (dates[0] > dxyScores.Dates[i]) continue;

          if (dxyScores.Dates[i].Month == 12 && (dxyScores.Dates[i].Day == 25 || dxyScores.Dates[i].Day == 26))
            continue;

          double dxyToday = dxyScores.Data[i + optArgs_.SwitchDayOffset];
          double dxyYest = dxyScores.Data[i + optArgs_.SwitchDayOffset - 1];

          if (dxyToday >= optArgs_.SwitchThreshold && dxyYest < optArgs_.SwitchThreshold)
          {
            if (dates.Contains(dxyScores.Dates[i]) == false)
            {
              dates.Add(dxyScores.Dates[i]);
              triggerDates.Add(dxyScores.Dates[i]);
            }
          }
          else if (dxyToday < optArgs_.SwitchThreshold && dxyYest >= optArgs_.SwitchThreshold)
          {
            if (dates.Contains(dxyScores.Dates[i]) == false)
            {
              dates.Add(dxyScores.Dates[i]);
              triggerDates.Add(dxyScores.Dates[i]);
            }
          }
        }
        QuickSort.Sort<DateTime>(dates);
      }
      //else if (optArgs_.SwitchExpReturn == SwitchSignType.COTMonWts)
      //{
      //  ConstructGen<double> cotWts = Backtests.getWE(Strat.COT1Mon).Key;
      //  dxyScores = cotWts.SumRows();
      //  dxyScores = dxyScores.MultiplyBy(-1d);
      //}

      int numCcys = Singleton<FXIDs>.Instance.Count;
      ConstructGen<double> wts = new ConstructGen<double>(Singleton<FXIDs>.Instance.ColumnHeadings);

      /* lincon */
      double[,] lincon = new double[6, numCcys + 1];

      /* minlincon & maxlincon */
      double[,] minlincon = new double[6, 1];
      double[,] maxlincon = new double[6, 1];
      {
        minlincon[0, 0] = 0d; minlincon[1, 0] = -10d; minlincon[2, 0] = 0d; minlincon[3, 0] = -10d; minlincon[4, 0] = 0d; minlincon[5, 0] = -10d;
        maxlincon[0, 0] = 10d; maxlincon[1, 0] = 0d; maxlincon[2, 0] = 10d; maxlincon[3, 0] = 0d; maxlincon[4, 0] = 10d; maxlincon[5, 0] = 0d;
      }

      /* opt horizon */
      string optHorizon = "2W";

      /* USD constraints */
      double usdMin = -5d;
      double usdMax = 5d;

      usdMax = Math.Abs(optArgs_.USDAbsLimit);
      usdMin = 1d - Math.Abs(optArgs_.USDAbsLimit - 1d);

      /* target vol */
      double targetVol = 0.012159;

      /* equal expected return */
      double[] eerPos = new double[numCcys];
      for (int i = 0; i < eerPos.Length; ++i) eerPos[i] = optArgs_.ReturnMagnitude == 0d ? 0.1 : Math.Abs(optArgs_.ReturnMagnitude);
      double[] eerNeg = new double[numCcys];
      for (int i = 0; i < eerNeg.Length; ++i) eerNeg[i] = optArgs_.ReturnMagnitude == 0d ? -0.1 : -Math.Abs(optArgs_.ReturnMagnitude);

      foreach (DateTime date in dates)
      {
        if (optArgs_.StartDate != null && date <= optArgs_.StartDate.Value)
          continue;

        Logger.Debug(string.Format("Generatig weights for {0}", date.ToString("dd-MMM-yyy")), typeof (RVOLOpt));

        /* covariance */

        CovarianceItem simCov = (optArgs_.SimCov == VolType.covar)
          ? Singleton<CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(date)
          : Singleton<FXHistCovar>.Instance.FindForDate(date, optArgs_.HistCovarWindowLength);
        CovarianceItem scaleCov = (optArgs_.ScaleCov == VolType.covar)
          ? Singleton<CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(date)
          : Singleton<FXHistCovar>.Instance.FindForDate(date, optArgs_.HistCovarWindowLength);



        /* tcosts */
        double[] tcosts = new double[numCcys];
        {
          if (optArgs_.IncludeTransactionsCosts)
          {
            int endIndex = tranCosts.Dates.Contains(date) ? tranCosts.Dates.IndexOf(date) - 1 : tranCosts.Dates.Count - 1;
            tcosts = tranCosts.GetValues(tranCosts.Dates[endIndex]);
          }
        }

        /* oldWts */
        double[] prevWts = new double[numCcys];
        {
          if (optArgs_.PrevWts != null)
            prevWts = optArgs_.PrevWts;
          else if (wts.Dates.Count > 0)
            prevWts = wts.GetValues(wts.Dates[wts.Dates.Count - 1]);
        }

        /* mins & maxs */
        double[] mins = new double[numCcys];
        double[] maxs = new double[numCcys];
        {
          for (int i = 0; i < numCcys; ++i)
          {
            Currency ccy = Singleton<FXIDs>.Instance[i];

            // must be zero for non-elegible currencies
            if (ccy.IsValid(date) == false) continue;

            // exclude this currency
            if (exclude.Contains(ccy.Code)) continue;

            //mins[i] = exclude.Contains(ccy.Code) ? 0d : !ccy.IsGroup(FXGroup.G10) ? -0.121591 : -0.3039775;
            //maxs[i] = exclude.Contains(ccy.Code) ? 0d : !ccy.IsGroup(FXGroup.G10) ? 0.121591 : 0.3039775;

            switch (optArgs_.WeightsSplitType)
            {
              case WtsSplitType.G10_EM:
                {
                  maxs[i] = ccy.IsGroup(FXGroup.G10) ? Math.Abs(optArgs_.G10MaxWeight) : Math.Abs(optArgs_.EMMaxWeight);
                }
                break;
              case WtsSplitType.G10_NDF_NonNDFEM:
                {
                  if (ccy.IsGroup(FXGroup.G10))
                    maxs[i] = Math.Abs(optArgs_.G10MaxWeight);
                  else if (ccy.IsGroup(FXGroup.NDF))
                    maxs[i] = Math.Abs(optArgs_.NDFMaxWeight);
                  else
                    maxs[i] = Math.Abs(optArgs_.NonNDFEMMaxWeight);
                }
                break;
              case WtsSplitType.Custom:
                {
                  maxs[i] = Math.Abs(optArgs_.CustomMaxMins[i]);
                }
                break;
            }

            mins[i] = -maxs[i];
          }
        }

        /* neg expected return or not */
        if (double.IsNaN(optArgs_.SwitchThreshold) == false)  // ... if we're looking for a threshold
        {
          double score = dxyScores.ValueOnDate(date, optArgs_.SwitchDayOffset);
          if (score > optArgs_.SwitchThreshold)
            doNeg = true;
          else
            doNeg = false;
        }

        /* go */
        //IMOptPortfolio(targetVol, cov, carry, tcosts, prevWts, mins, maxs, lincon, minlincon, maxlincon, optHorizon, lastArg);

        switch (optArgs_.ExpectedReturnType)
        {
          case ExpectedReturnType.Equal:
            // do nothing - is default option
            break;
          case ExpectedReturnType.OneOverVol:
          {
            double[] vols = simCov.IndividualVols;
            for (int i = 0; i < eerPos.Length; ++i)
            {
              eerPos[i] = 1d/vols[i];
              eerNeg[i] = -1d/vols[i];
            }
          }
            break;
          case ExpectedReturnType.EqualExceptLowestCorrel_1:
          case ExpectedReturnType.EqualExceptLowestCorrel_2:
          {
            var rankThreshold = 0d;

            switch (optArgs_.ExpectedReturnType)
            {
              case ExpectedReturnType.EqualExceptLowestCorrel_1:
                rankThreshold = 1.1d;
                break;
              case ExpectedReturnType.EqualExceptLowestCorrel_2:
                rankThreshold = 2.1d;
                break;
            }

            var corrRanks =
              Singleton<CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(date, 5)
                .GetIndividualAverageCorrelations()
                .ToRanks(ascending_: true);

            for (int i = 0; i < eerPos.Length; ++i)
            {
              var rank = corrRanks[i];
              eerNeg[i] = (rank <= rankThreshold) ? 0.1 : -0.1;
              eerPos[i] = (rank <= rankThreshold) ? -0.1 : 0.1;
            }
          }
            break;
          case ExpectedReturnType.EqualExceptLowestCorrel_pct10:
          {
            var pctThreshold = 0.1d;

            var indivAvgCorrelations = Singleton<CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(date, 5)
              .GetIndividualAverageCorrelations();

            double min = indivAvgCorrelations.Min();
            double max = indivAvgCorrelations.Max();

            double threshold = min + ((max - min)*pctThreshold);

            for (int i = 0; i < eerPos.Length; ++i)
            {
              eerNeg[i] = (indivAvgCorrelations[i] <= threshold) ? 0.1 : -0.1;
              eerPos[i] = (indivAvgCorrelations[i] <= threshold) ? -0.1 : 0.1;
            }
          }
            break;
        }

        if (optArgs_.OptType == OptimationType.Excel)
        {

          var result = Singleton<ExcelOptimizer>.Instance.DoIt(
            numCcys, targetVol, simCov.Data, doNeg ? eerNeg : eerPos, tcosts, prevWts, mins, maxs, usdMin, usdMax, optHorizon,
            date);

          //if (result.OptimizationResult != Optimizer.CarryOptResult.OptResult.OK_SolutionFoundAllConstraintsSatisfied)
          //  System.Diagnostics.Debugger.Break();

          double[] dateWts = result.Wts;

          if (result.Wts.SumAbs() == 0d)
            System.Diagnostics.Debugger.Break();

          // cross-sectional demean?
          if (optArgs_.CSDemean)
          {
            double sum = 0d;
            double count = 0d;
            for (int i = 0; i < dateWts.Length; ++i)
              if (dateWts[i] != 0d)
              {
                sum += dateWts[i];
                count += 1d;
              }
            double avg = sum/count;
            for (int i = 0; i < dateWts.Length; ++i)
              if (dateWts[i] != 0d)
                dateWts[i] -= avg;

            dateWts = scaleCov.ScaleSeries(dateWts, CovarianceItem.VolFromVaR(0.02));
          }

          wts.SetValues(date, dateWts);
        }
        else if (optArgs_.OptType == OptimationType.SolverFoundation)
        {
          var model = new RvolSolveModel(
            simCov,
            Singleton<FXIDs>.Instance.Select(
              (x, i) => new CurrencyLine(x, doNeg ? eerNeg[i] : eerPos[i], mins[i], maxs[i])).ToArray(),
            targetVol)
          {
            SumOfWeightsMin=0d,
            SumOfWeightsMax=0d
          };

          new RvolSolver().Solve(model);

          wts.SetValues(date, model.CurrencyLines.Select(x => x.Weight).ToArray());
        }
      }

      if(optArgs_.OptType==OptimationType.Excel)
        Singleton<ExcelOptimizer>.Instance.Dispose();

      return new RVOlOptResult()
      {
        TArgs = args,
        Weights = wts,
        TriggerDates = triggerDates
      };
      //return new KeyValuePair<TraderArgs, Construct>(args, wts);
    }
コード例 #14
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
 protected abstract ReturnsEval.DataSeriesEvaluator doPnl(TraderArgs args_, ConstructGen<double> wts_);
コード例 #15
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public ReturnsEval.DataSeriesEvaluator DoPnl(TraderArgs args_)
    {
      ConstructGen<double> wts = GetWeights(args_);

      return DoPnl(args_, wts);
    }
コード例 #16
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
 public ReturnsEval.DataSeriesEvaluator DoPnl(TraderArgs args_, ConstructGen<double> wts_)
 {
   return doPnl(args_, wts_);
 }
コード例 #17
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
 public abstract double[] GetContToVar(double[] wts_, DateTime date_, TraderArgs args_);
コード例 #18
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
 public abstract ConstructGen<double> ScaleWeights(ConstructGen<double> weights_, double targetVol_, TraderArgs args_);
コード例 #19
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    private static int numValidProductsOnDate(DateTime date_, TraderArgs args_)
    {
      int count = 0;

      foreach (ProductBase pb in args_.Products)
        if (pb.IsValid(date_))
          ++count;

      return count;
    }
コード例 #20
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public static ConstructGen<double> getFilters(TraderArgs args_, List<DateTime> rebalDates_, IDictionary<ProductBase,List<DatedDataCollectionGen<double>>> resultsFilter_)
    {
      ConstructGen<double> ret = new ConstructGen<double>(args_.Products.Count);

      if (resultsFilter_==null || resultsFilter_.Count == 0)
      {
        ret.InitialiseToValue(rebalDates_, 1d);
      }
      else
      {
        for (int j = 0; j < args_.Products.Count; ++j)
        {
          DatedDataCollectionGen<double> dataForProductAndFilter = resultsFilter_[args_.Products[j]][0];

          foreach (DateTime date in rebalDates_)
          {
            ret.SetValue(
              date,
              j,
              dataForProductAndFilter.ValueOnDate(date, args_.DayOffset));
          }
        }
      }

      // use this opportunity to count out those products that are not valid on this date
      for (int j = 0; j < args_.Products.Count; ++j)
      {
        foreach (DateTime date in rebalDates_)
        {
          if (args_.Products[j].IsValid(date) == false)
            ret.SetValue(date, j, double.NaN);
        }
      }

      // ConstructDisplay.Show(ret, args_.Products.ToArray(), "Filter series");

      return ret;
    }
コード例 #21
0
ファイル: TraderGen.cs プロジェクト: heimanhon/researchwork
 public override double[] GetContToVar(double[] wts_, DateTime date_, TraderArgs args_)
 {
   throw new NotImplementedException();
 }
コード例 #22
0
ファイル: TraderGen.cs プロジェクト: heimanhon/researchwork
 public override ConstructGen<double> ScaleWeights(ConstructGen<double> weights_, double targetVol_, TraderArgs args_)
 {
   return DoScaleWeights(weights_, targetVol_, args_);
 }
コード例 #23
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
 public static void processToTrigger(ConstructGen<double> wts_, TraderArgs args_)
 {
   processToTrigger(wts_, args_, null);
 }
コード例 #24
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    private ConstructGen<double>[] getWeights(TraderArgs args_, List<DateTime> rebalDates_, ConstructGen<double> filter_)
    {
      if (m_resultsWts.Count == 0)
        return null;

      ConstructGen<double>[] allWts = new ConstructGen<double>[args_.WtIndicators.Count];

      // go through all wtIndicators - will normally only be one
      for (int i = 0; i < args_.WtIndicators.Count; ++i)
      {
        ConstructGen<double> all_c,rebal_c;

        int length = args_.Products.Count;

        all_c = new ConstructGen<double>(length);
        rebal_c = new ConstructGen<double>(length);

        for (int j = 0; j < args_.Products.Count; ++j)
        {
          // extract the signal series for this wtIndicator and product
          DatedDataCollectionGen<double> dataForProductAndIndicator = m_resultsWts[args_.Products[j]][i];

          // put the data in the contruct that represents the signal at every point
          for (int y = 0; y < dataForProductAndIndicator.Length; ++y)
            all_c.SetValue(
              dataForProductAndIndicator.Dates[y],
              j,
              dataForProductAndIndicator.Data[y]);

          // put the data in the construct that represents the signal just on rebal days
          // NOTE: is offset by 1 day so not in sample
          foreach (DateTime d in rebalDates_)
          {
            //if (d == new DateTime(2010, 3, 19))
            //  System.Diagnostics.Debugger.Break();
            if (args_.Products[j].IsValid(d))
              rebal_c.SetValue(d, j, dataForProductAndIndicator.ValueOnDate(d, args_.DayOffset));
          }
        }

        // c is now a representation of the signal for all products on all days

        // do we want the product of the weights to determine which products can have positions on different days?
        if (args_.UseWeightsForFilter)
        {
          foreach (DateTime d in rebalDates_)
          {
            for (int ii = 0; ii < rebal_c.ArrayLength; ++ii)
              if (double.IsNaN(rebal_c.GetValue(d, ii)))
                filter_.SetValue(d, ii, double.NaN);
          }
        }

        // multiply it by the filter to get rid of non-eligible days

        rebal_c = multiply(rebal_c, filter_,false);

        //ConstructDisplay.Show(rebal_c, args_.Products.ToArray(), "raw signal * filter");

        // now need to scale the weights based on the weighting scheme supplied on the signal indicator 

        // create a construct which will be the multiple

        foreach (SI.Research.Backtest.Builder.Model.WtScheme transform in args_.WtIndicators[i].TransformList)
        {
          ConstructGen<double> wts = new ConstructGen<double>(length);
          wts.InitialiseToValue(rebalDates_,1d);

          transform.DoWeights(rebal_c, all_c, wts, args_.Products,filter_);

          wts = multiply(wts, filter_, true);

          rebal_c = wts;

          //ConstructDisplay.Show(rebal_c, args_.Products.ToArray(), "weights");
        }

        //ConstructDisplay.Show(rebal_c, new object[] { "wts" }, "transformed weights");

        allWts[i] = rebal_c;
      }

      return allWts;
    }
コード例 #25
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    public ConstructGen<double> GetWeights(TraderArgs args_)
    {
      generateRawResults(args_);

      // generate all indicators
      List<DateTime> rebalDates = getRebalDates(args_);

      // save them so we can use them later
      args_.RebalDates = rebalDates;

      // get the filter construct first
      ConstructGen<double> filter = getFilters(args_, rebalDates, m_resultsFilter);

      //ConstructDisplay.Show(filter, args_.Products.ToArray(), "Filter Values");

      // get the wts 
      ConstructGen<double>[] wts = getWeights(args_, rebalDates, filter);

      if (wts.Length > 0 && args_.CombineWeightArgs != null)
      {
        // do we want to scale each signal before combining?
        if (args_.CombineWeightArgs.ScaleBeforeCombine)
          for (int i = 0; i < wts.Length; ++i)
            wts[i] = ScaleWeights(wts[i], args_.ScaleToThisVol, args_);

        // do we want to scale the allocation to each signal?
        if (args_.CombineWeightArgs.ScaleWeightSignalsEnabled)
        {
          double currAlloc = args_.CombineWeightArgs.StratWeightStartAlloc;

          for (int i = 0; i < wts.Length; ++i)
          {
            wts[i] = wts[i].MultiplyBy(currAlloc);

            currAlloc += args_.CombineWeightArgs.StratWeightAllocIncrement;
          }
        }
      }

      // combine the different signals
      ConstructGen<double> c = wts[0];
      if (args_.CombineWeightArgs != null && args_.CombineWeightArgs.CombineMethod == StratCombineMethod.MULT)
      {
        c = wts[0];
        for (int i = 1; i < wts.Length; ++i)
          c = multiply(c, wts[i], false);
      }
      else if (args_.CombineWeightArgs != null && args_.CombineWeightArgs.CombineMethod == StratCombineMethod.AGREE)
      {
        c = wts[0];
        for (int i = 1; i < wts.Length; ++i)
          c = agreeSign(c, wts[i]);
      }
      else if (args_.CombineWeightArgs != null && args_.CombineWeightArgs.CombineMethod == StratCombineMethod.ADD)
      {
        c = wts[0];
        for (int i = 1; i < wts.Length; ++i)
          c = c.Plus(wts[i]);
      }
      else if (args_.CombineWeightArgs != null && args_.CombineWeightArgs.CombineMethod == StratCombineMethod.LIST)
      {
        System.Diagnostics.Debug.Assert(args_.CombineWeightArgs.AllocList != null, "Combine method has been set to 'LIST' but no allocation list has been set");

        System.Diagnostics.Debug.Assert(args_.CombineWeightArgs.AllocList.ArrayLength == wts.Length, "Set of weights to combine doesn't match arraylength of ConstructGen<double> that has been set to express the allocations.");

        // get a list of common dates
        List<DateTime> commondates = new List<DateTime>();
        foreach (DateTime date in wts[0].Dates)
        {
          for (int i = 1; i < wts.Length; ++i)
            if (wts[i].Dates.Contains(date) == false)
              continue;

          commondates.Add(date);
        }

        ConstructGen<double> comb = new ConstructGen<double>(wts[0].ArrayLength);

        for (int i = 0; i < wts.Length; ++i)
        {
          foreach (DateTime date in commondates)
          {
            if(comb.Dates.Contains(date)==false)
              comb.SetValues(date,new double[comb.ArrayLength]);

            double alloc = args_.CombineWeightArgs.AllocList.GetValue(date, i);

            for (int j = 0; j < comb.ArrayLength; ++j)
              comb.AddValue(date, j, alloc * wts[i].GetValue(date, j));
          }
        }

        c = comb;

      }
      else if (args_.CombineWeightArgs == null && wts.Length > 1)
        throw new Exception("Don't know how to combine the signals into one.");
      else if (args_.CombineWeightArgs != null)
        throw new Exception("Strategy combine method not implemented");

      // scale to the target vol
      if (args_.ScaleToVol)
        c = ScaleWeights(c, args_.ScaleToThisVol, args_);

      // if we want to 
      if (args_.RebalFrequency == RebalFreq.Trigger)
        processToTrigger(c, args_, this);


      //ConstructDisplay.Show(c, args_.Products.ToArray(), "final wts");

      c.ColumnHeadings = args_.Products.Select<ProductBase, string>(x => x.ToString()).ToArray<string>();

      return c;
    }
コード例 #26
0
ファイル: Trader.cs プロジェクト: heimanhon/researchwork
    private List<DateTime> getRebalDates(TraderArgs args_)
    {
      if (args_.RebalDates != null)
        return args_.RebalDates;

      return GetRebalDates(args_, findStartDate(args_));
    }
コード例 #27
0
ファイル: Carry.cs プロジェクト: heimanhon/researchwork
    public static KeyValuePair<TraderArgs, ConstructGen<double>> GetBackTestWeights(CarryOptARgs args_)
    {
      TraderArgs args = new TraderArgs();

      Array.ForEach(Singleton<FXIDs>.Instance.ToArray(), x => args.Products.Add(ProductFX.GetCached(x)));

      args.RebalFrequency = args_.Freq;
      args.DayOfWeek = DayOfWeek.Tuesday;
      args.ParticularDate = args_.ParticularRebalDate;

      var dates = args_.Freq == RebalFreq.ParticularDate
        ? Trader.GenerateRebalDates(args.RebalFrequency, args.ParticularDate)
        : Trader.GetRebalDates(args, MyCalendar.NextDayOfWeek(SI.Data.DataConstants.DATA_START, DayOfWeek.Tuesday));

      var carryCon =
        Singleton<FXCarry>.Instance.GetData(
          startDate_: MyCalendar.PrevWeekDay(dates[0].AddDays(-2d*args_.DaysToAverageCarryNDF)),
          endDate_: DateTime.Today);

      var tranCosts = Singleton<FXTransactionCosts>.Instance.GetData(MyCalendar.PrevWeekDay(dates[0].AddDays(-10d)), DateTime.Today, false);
      var dxyScores = Singleton<DXYScore_21>.Instance.Scores;

      DatedDataCollectionGen<double> outScores = null;
      double outthreshold = 0d;

      switch (args_.OutMethod)
      {
        case CarryOptARgs.CarryOutMethod.ATMVolsPercentileAbove50:
          outScores = Singleton<ATMVolsRank>.Instance.ATM_1W_o1Y;
          outthreshold = 0.5;
          break;
        case CarryOptARgs.CarryOutMethod.MOVEIndexPercentilAbove50:
          outScores = Singleton<MOVEScore_21>.Instance.Pxs.ToPercentileRanked(252);
          outthreshold = 0.5;
          break;
        default:
          outScores = null;
          outthreshold = 0d;
          break;
      }


      int numCcys = args.Products.Count;

      var wts = new ConstructGen<double>(Singleton<FXIDs>.Instance.ColumnHeadings);

      /* lincon */
      double[,] lincon = new double[6, numCcys + 1];

      /* minlincon & maxlincon */
      double[,] minlincon = new double[6, 1];
      double[,] maxlincon = new double[6, 1];
      {
        minlincon[0, 0] = 0d; minlincon[1, 0] = -10d; minlincon[2, 0] = 0d; minlincon[3, 0] = -10d; minlincon[4, 0] = 0d; minlincon[5, 0] = -10d;
        maxlincon[0, 0] = 10d; maxlincon[1, 0] = 0d; maxlincon[2, 0] = 10d; maxlincon[3, 0] = 0d; maxlincon[4, 0] = 10d; maxlincon[5, 0] = 0d;
      }

      /* opt horizon */
      string optHorizon = "2W";

      /* USD constraints */
      double usdMin = 1d;
      double usdMax = 1d;

      /* target vol */
      double targetVol = args_.TargetVol;

      foreach (DateTime date in dates)
      {
        if (args_.StartDate != null && date <= args_.StartDate.Value)
          continue;

        var simCov = getCovarianceItem(date, args_.SimCov, args_.HistCovarWindowLength);
        var scaleCov = (args_.ScaleCov == args_.SimCov) ? simCov : getCovarianceItem(date, args_.ScaleCov, args_.HistCovarWindowLength);

        /* covariance */
        double[,] cov = simCov.Data;

        /* carry */
        double[] carry = new double[numCcys];
        {
          // need to take 5 day average starting on the day before the date we're rebalancing
          int endIndex = carryCon.Dates.Contains(date) ? carryCon.Dates.IndexOf(date) - 1 : carryCon.Dates.Count - 1;
          for (int i = 0; i < carryCon.ArrayLength; ++i)
          {
            // currency isn't valid = carry stays at zero
            if (Singleton<FXIDs>.Instance[i].IsValid(date) == false)
              continue;

            var cryLength = Singleton<FXIDs>.Instance[i].IsGroup(FXGroup.NDF)
              ? args_.DaysToAverageCarryNDF
              : args_.DaysToAverageCarry;

            double sum = 0d;
            for (int j = 0; j < cryLength; ++j)
              sum += carryCon.GetValue(carryCon.Dates[endIndex - j], i);

            carry[i] = sum / Convert.ToDouble(cryLength);

            Logger.Debug(
              string.Format("Carry of {0} over {1} = {2}", Singleton<FXIDs>.Instance[i], cryLength, carry[i]),
              typeof (Carry));
          }
        }

        /* tcosts */
        double[] tcosts = new double[numCcys];
        {
          if (args_.IncludeTranCosts)
          {
            int endIndex = tranCosts.Dates.Contains(date) ? tranCosts.Dates.IndexOf(date) - 1 : tranCosts.Dates.Count - 1;
            tcosts = tranCosts.GetValues(tranCosts.Dates[endIndex]);
          }
        }

        /* oldWts */
        double[] prevWts = new double[numCcys];
        {
          if (args_.PrevWeights != null)
            prevWts = args_.PrevWeights;
          else if (wts.Dates.Count > 0)
            prevWts = wts.GetValues(wts.Dates[wts.Dates.Count - 1]);
        }


        /* mins & maxs */
        double[] mins = new double[numCcys];
        double[] maxs = new double[numCcys];
        {
          for (int i = 0; i < numCcys; ++i)
          {
            Currency ccy = Singleton<FXIDs>.Instance[i];

            // must be zero for non-elegible currencies
            if (ccy.IsValid(date) == false) continue;

            mins[i] = !args_.ShouldIncludeCurrency(date,ccy) ? 0d : -args_.GetWeightConstraint(ccy); 
            maxs[i] = !args_.ShouldIncludeCurrency(date, ccy) ? 0d : args_.GetWeightConstraint(ccy); 
          }
        }

        switch (args_.USDConstraints)
        {
          case CarryOptARgs.DXYConstraint.Dynamic:
          {
            /* USD min max */
            double score = (args_.DXYScore != 0d) ? args_.DXYScore : dxyScores.ValueOnDate(date, -1);
            if (score > 1d)
            {
              usdMin = 1d;
              usdMax = 5d;
            }
            else if (score < -1d)
            {
              usdMin = -5d;
              usdMax = 1d;
            }
            else
            {
              usdMin = 1d;
              usdMax = 1d;
            }
          }
            break;
          case CarryOptARgs.DXYConstraint.Flat:
          {
            usdMin = 1d;
            usdMax = 1d;
          }
            break;
          case CarryOptARgs.DXYConstraint.None:
          {
            usdMin = -5d;
            usdMax = 5d;
          }
            break;
        }

        var result = Singleton<ExcelOptimizer>.Instance.DoIt(
          numCcys, targetVol, cov, carry, tcosts, prevWts, mins, maxs, usdMin, usdMax, optHorizon, date);

        double[] optWts = result.Wts;

        if (args_.ScaleCov != args_.SimCov)
          optWts = scaleCov.ScaleSeries(optWts, targetVol);

        if (outScores != null && outScores.ValueOnDate(date) > outthreshold)
          optWts = new double[optWts.Length];

        wts.SetValues(date, optWts);
      }

      Singleton<ExcelOptimizer>.Instance.Dispose();

      return new KeyValuePair<TraderArgs, ConstructGen<double>>(args, wts);
    }