static public List<Term> GetTermFromPeriod( DateTime positionStartDate, DateTime positionEndDate, PeriodicTimeDefinition termLength ) { List<Term> resultTerms = new List<Term>(); var availableTermDates = termLength.AvailableDates; // the date of the first term var firstTermEndDate = availableTermDates.Where(d => d > positionStartDate).Min(); var lastTermEndDate = availableTermDates.Where(d => d >= positionEndDate).Min(); var effectiveDates = availableTermDates .Where(d => d >= positionStartDate && d <= lastTermEndDate); for (int i = 0; i < effectiveDates.Count() ; i++) { if (i == 0) resultTerms.Add(new Term(positionStartDate, firstTermEndDate)); else if( effectiveDates.ElementAtOrDefault(i+1) != DateTime.MinValue) resultTerms.Add( new Term(effectiveDates.ElementAt(i), effectiveDates.ElementAt(i + 1) )); } return resultTerms; }
public void GetTransformedPositionRecordsTest() { FXEntities.FXEntities fxEntities = new FXEntities.FXEntities(); CurrencyDataSource currencyDataSource = new CurrencyDataSource(fxEntities); var startDate = new DateTime(2000, 1, 4); var endDate = new DateTime(2003, 1, 4); var periodicTimeDef = new PeriodicTimeDefinition(3, PeriodicType.Month); periodicTimeDef.Initialize(startDate, endDate); ProfitCalculationEngine_Accessor target = new ProfitCalculationEngine_Accessor(currencyDataSource); PositionRuntime positionRuntime = new PositionRuntime(FXStrategy.Interpreter.PositionType.Long); positionRuntime.PositionRecords.Add(new PositionRecord( new DateTime(2000, 1, 4), new Currency("USD"), new Currency("EUR"), FXStrategy.Interpreter.PositionType.Long, positionRuntime) { EndDate = new DateTime(2001,3,2) }); //var actual = target.GetTransformedPositionRecords(positionRuntime, periodicTimeDef); //Assert.AreEqual(actual.Count, 6); //Assert.IsTrue(actual.ElementAt(5).Type == FXStrategy.Interpreter.PositionType.Short); //Assert.IsTrue(actual.Take(5).All(t => t.Type == FXStrategy.Interpreter.PositionType.Long)); }
public void GetTermFromPeriodTest() { DateTime positionStartDate = new DateTime(2000,1,4); DateTime positionEndDate = new DateTime(2000,7,15); PeriodicTimeDefinition termLength = new PeriodicTimeDefinition(3, PeriodicType.Month); termLength.Initialize(positionStartDate, new DateTime(2001,1,1)); List<Term> actual; actual = TermManager.GetTermFromPeriod(positionStartDate, positionEndDate, termLength); Assert.AreEqual(3, actual.Count); }
public void CanExecuteTest() { PeriodicTimeDefinition target = new PeriodicTimeDefinition( 3, PeriodicType.Month ); DateTime startDate = new DateTime(2000,1,7); DateTime currentDate = new DateTime(2000,4,7); bool expected = true; // TODO: Initialize to an appropriate value bool actual; target.Initialize(startDate, currentDate); actual = target.CanExecute(currentDate); Assert.AreEqual(expected, actual); }
/// <summary> /// Calculate the total profit from all positions /// </summary> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <param name="termLength"></param> private void CalculateReturnIndex(DateTime startDate, DateTime endDate, PeriodicTimeDefinition termLength) { _returnOverTime = new List<TimeSeriesData>(); _indexOverTime = new List<TimeSeriesData>(); int numberOfPositions = _individualPositionIndex.Keys.Count; var returns = _individualPositionIndex.Values.SelectMany(d => d); // except first date var effectiveTermDates = termLength.AvailableDates.Where(d => d != startDate); decimal averageReturn; decimal currentIndex = 100; foreach (var date in _effectiveDates) { var targetRecords = returns.Where(r => r.Time == date); if (targetRecords == null || targetRecords.Count() == 0) continue; averageReturn = returns.Where(r => r.Time == date).Average(r => r.Value); // if it is the maturity date, accumulate the profit if (effectiveTermDates.Contains(date)) { currentIndex = currentIndex * (1 + averageReturn); _indexOverTime.Add(new TimeSeriesData() { Time = date, Value = currentIndex }); } else { _indexOverTime.Add(new TimeSeriesData() { Time = date, Value = currentIndex * (1 + averageReturn) }); } _returnOverTime.Add(new TimeSeriesData() { Time = date, Value = averageReturn }); } }
/// <summary> /// Calculate returns from the position records in the position run time /// </summary> /// <param name="positionRunTimeList">list of positions (from the runtime)</param> /// <param name="startDate">start date of the back-testing analysis</param> /// <param name="endDate">end date of the back-testing analysis</param> /// <param name="termLength">Length of forward contract</param> public void Evaluate(List<PositionRuntime> positionRunTimeList, DateTime startDate, DateTime endDate, PeriodicTimeDefinition termLength) { if (termLength.AvailableDates == null) termLength.Initialize(startDate, endDate); _effectiveDates = Util.DateTimeHelper.GetWeekdaysDate(startDate, endDate); _individualPositionIndex = new Dictionary<PositionRuntime, List<TimeSeriesData>>(); // initialize data set _currencyDataSource.PreLoad(); // Calculate profit for each position parallely positionRunTimeList.AsParallel().ForAll(position => CalculateIndividualPositionProfitIndexes(startDate,endDate,termLength,position)); CalculateReturnIndex(startDate,endDate,termLength); }
public MovingAverage(TimeDataSetAccessor timeDataSetAccessor, PeriodicTimeDefinition length, Expression requestDate) :base(timeDataSetAccessor) { _length = length; _requestDate = requestDate; }
/// <summary> /// Split position records into records in the length of termLength /// </summary> /// <param name="originalPositionRecords"></param> /// <param name="termLength"></param> /// <returns></returns> private List<PositionRecord> TransformPositionRecords( PositionRuntime positionRuntime, PeriodicTimeDefinition termLength) { List<DateTime> termEffectiveDates = termLength.AvailableDates; List<PositionRecord> transformedPositionRecords = new List<PositionRecord>(); foreach (var positionRecord in positionRuntime.PositionRecords) { // list of terms that available for the position var effectiveTerms = TermManager.GetTermFromPeriod(positionRecord.StartDate, positionRecord.EndDate, termLength); // create terms for each position record effectiveTerms.ForEach(t => transformedPositionRecords.Add(new PositionRecord( t.StartDate, t.EndDate, positionRecord.CurrencyInPosition, positionRecord.BaseCurrency, positionRecord.Type, positionRuntime))); if (positionRecord.EndDate != effectiveTerms.Last().EndDate) { // for the case ending the record within a forward contract // an opposite position will be opened transformedPositionRecords.Add(new PositionRecord( effectiveTerms.Last().StartDate, effectiveTerms.Last().EndDate, positionRecord.CurrencyInPosition, positionRecord.BaseCurrency, (positionRecord.Type == PositionType.Long) ? PositionType.Short : PositionType.Long, positionRuntime)); } } return transformedPositionRecords; }
/// <summary> /// Calculate profit for an individual position over time /// </summary> /// <param name="startDate">start date of the back-testing analysis</param> /// <param name="endDate">end date of the back-testing analysis</param> /// <param name="termLength">Length of forward contract</param> /// <param name="position">the position for calculation</param> private void CalculateIndividualPositionProfitIndexes(DateTime startDate, DateTime endDate, PeriodicTimeDefinition termLength, PositionRuntime position) { AssignEndDateToLastRecord(endDate, position); List<PositionRecord> transformedRecord = TransformPositionRecords(position, termLength); List<TimeSeriesData> positionIndexes = new List<TimeSeriesData>(); foreach (var record in transformedRecord) { DateTime effectiveStartDate = GetEffectiveStartDate(record); DateTime effectiveEndDate = GetEffectiveEndDate(record); decimal startExchangeRate = GetExchangeRateBaseOnPosType(record, effectiveStartDate); decimal variableInRate = GetIntRate(record.CurrencyInPosition.Name, effectiveStartDate) / (decimal)100; decimal baseInRate = GetIntRate(record.BaseCurrency.Name, effectiveStartDate) / (decimal)100; decimal forwardRate = CalculateForwardRate((effectiveEndDate - effectiveStartDate).Days, startExchangeRate, baseInRate, variableInRate); foreach (var currentDate in DateTimeHelper.GetWeekdaysDate(record.StartDate, record.EndDate)) { decimal curExchangeRate = GetExchangeRate(record, currentDate); decimal curProfit = CalculateProfitBaseOnPosType(record, forwardRate, curExchangeRate); var existingIndex = positionIndexes.Where(d => d.Time == currentDate).FirstOrDefault(); if (existingIndex == null) { positionIndexes.Add(new TimeSeriesData() { Time = currentDate, Value = curProfit }); } else { existingIndex.Value += curProfit; } } } _individualPositionIndex.Add(position, positionIndexes); }