public void SetDefaultPriceForInstructionWhenNecessary(Instruction instruction)
        {
            if (_settings == null)
            {
                return;
            }

            if (instruction.Price == null)
            {
                TradingPrice price;

                if (instruction.Action == TradingAction.OpenLong)
                {
                    price = new TradingPrice(_settings.OpenLongPricePeriod, _settings.OpenLongPriceOption, 0.0);
                }
                else if (instruction.Action == TradingAction.CloseLong)
                {
                    price = new TradingPrice(_settings.CloseLongPricePeriod, _settings.CloseLongPriceOption, 0.0);
                }
                else
                {
                    throw new InvalidOperationException(
                              string.Format("unsupported action {0}", instruction.Action));
                }

                instruction.Price = price;
            }
        }
Beispiel #2
0
 private void CreateInstructionForBuying(ITradingObject tradingObject, TradingPrice price, string comments, object[] relatedObjects)
 {
     _instructionsInCurrentPeriod.Add(
         new OpenInstruction(_period, tradingObject, price)
     {
         Comments               = comments,
         Volume                 = 0,   // will be filled in EstimateStoplossAndSizeOfNewPosition()
         StopLossGapForBuying   = 0.0, // will be filled in EstimateStoplossAndSizeOfNewPosition()
         StopLossPriceForBuying = 0.0, // will be filled in EstimateStoplossAndSizeOfNewPosition()
         RelatedObjects         = relatedObjects
     });
 }
Beispiel #3
0
        private void GenerateInstructions(ITradingObject[] tradingObjects, Bar[] bars)
        {
            // check if positions needs to be adjusted
            if (_positionAdjusting != null)
            {
                var instructions = _positionAdjusting.AdjustPositions();

                if (instructions != null)
                {
                    foreach (var instruction in instructions)
                    {
                        if (instruction.Action == TradingAction.OpenLong)
                        {
                            // comment out below code because evaluation result shows it will degrade performance.

                            //if (_globalSettings.AllowEnteringMarketOnlyWhenPriceIncreasing)
                            //{
                            //    var bar = bars[instruction.TradingObject.Index];
                            //    if (bar.ClosePrice <= bar.OpenPrice)
                            //    {
                            //        continue;
                            //    }
                            //}
                        }

                        _instructionsInCurrentPeriod.Add(instruction);
                    }
                }
            }

            for (var i = 0; i < tradingObjects.Length; ++i)
            {
                var tradingObject = tradingObjects[i];
                var bar           = bars[i];

                if (bar.Time == Bar.InvalidTime)
                {
                    continue;
                }

                Position[] positions;

                if (_context.ExistsPosition(tradingObject.Code))
                {
                    var temp = _context.GetPositionDetails(tradingObject.Code);
                    positions = temp as Position[] ?? temp.ToArray();
                }
                else
                {
                    positions = new Position[0];
                }

                // decide if we need to stop loss for some positions.
                bool isStopLost = false;
                List <CloseInstruction> stopLossInstructions = new List <CloseInstruction>();

                foreach (var position in positions)
                {
                    var stopLossPrice = double.MaxValue;

                    if (_globalSettings.StopLossByClosePrice)
                    {
                        if (position.StopLossPrice > bar.ClosePrice)
                        {
                            stopLossPrice = Math.Min(bar.ClosePrice, stopLossPrice);
                        }
                    }
                    else
                    {
                        if (position.StopLossPrice > bar.OpenPrice)
                        {
                            stopLossPrice = Math.Min(bar.OpenPrice, stopLossPrice);
                        }
                        else if (position.StopLossPrice > bar.LowestPrice)
                        {
                            stopLossPrice = Math.Min(position.StopLossPrice, stopLossPrice);
                        }
                    }

                    if (stopLossPrice < double.MaxValue)
                    {
                        TradingPrice price = new TradingPrice(
                            TradingPricePeriod.CurrentPeriod,
                            TradingPriceOption.CustomPrice,
                            stopLossPrice);

                        stopLossInstructions.Add(new CloseInstruction(_period, tradingObject, price)
                        {
                            Comments                = string.Format("stop loss @{0:0.000}", stopLossPrice),
                            SellingType             = SellingType.ByStopLossPrice,
                            StopLossPriceForSelling = stopLossPrice,
                            PositionIdForSell       = position.Id,
                            Volume = position.Volume,
                        });

                        isStopLost = true;
                    }
                }

                // decide if we need to exit market for this trading object.
                bool isExited = false;
                List <CloseInstruction> exitInstructions = new List <CloseInstruction>();
                if (positions.Any())
                {
                    foreach (var component in _marketExiting)
                    {
                        var marketExitingResult = component.ShouldExit(tradingObject);
                        if (marketExitingResult.ShouldExit)
                        {
                            exitInstructions.Add(new CloseInstruction(_period, tradingObject, marketExitingResult.Price)
                            {
                                Comments    = "Exiting market: " + marketExitingResult.Comments,
                                SellingType = SellingType.ByVolume,
                                Volume      = positions.Sum(p => p.Volume),
                            });

                            isExited = true;
                        }
                    }
                }

                if (isStopLost || isExited)
                {
                    // merge stop loss instructions and exit instructions
                    var instructions = MergeStopLossAndExitInstructions(stopLossInstructions, exitInstructions);

                    if (instructions.Any())
                    {
                        _instructionsInCurrentPeriod.AddRange(instructions);
                    }

                    // if there is position to stop loss or exit for given trading object,
                    // we will never consider entering market for the object.
                    continue;
                }

                // decide if we should enter market
                if (!positions.Any())
                {
                    if (!_globalSettings.AllowEnteringMarketOnlyWhenPriceIncreasing || bar.ClosePrice > bar.OpenPrice)
                    {
                        var  allResults = new List <MarketEnteringComponentResult>();
                        bool canEnter   = true;
                        foreach (var component in _marketEntering)
                        {
                            var marketEnteringResult = component.CanEnter(tradingObject);
                            if (!marketEnteringResult.CanEnter)
                            {
                                canEnter = false;
                                break;
                            }

                            allResults.Add(marketEnteringResult);
                        }

                        if (canEnter)
                        {
                            int nonDefaultPriceCount = allResults.Count(r => r.Price != null);
                            if (nonDefaultPriceCount > 1)
                            {
                                throw new InvalidOperationException("there are more than one non-default price for entering market");
                            }

                            TradingPrice price = nonDefaultPriceCount == 0
                                ? null
                                : allResults.Where(r => r.Price != null).First().Price;

                            var comments = "Entering market: " +
                                           string.Join(";", allResults.Select(r => r.Comments).Where(c => c != null));

                            var relatedObjects = allResults.Select(r => r.RelatedObject).Where(r => r != null);

                            CreateInstructionForBuying(
                                tradingObject,
                                price,
                                comments,
                                relatedObjects.Count() == 0 ? null : relatedObjects.ToArray());

                            _context.DumpBarsFromCurrentPeriod(tradingObject);
                        }
                    }
                }
            }

            // update default price for instructions
            foreach (var instruction in _instructionsInCurrentPeriod)
            {
                _context.SetDefaultPriceForInstructionWhenNecessary(instruction);
            }
        }
 public TradingStrategyComponentResult()
 {
     Comments = string.Empty;
     Price    = null;
 }