Esempio n. 1
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);
            }
        }
Esempio n. 2
0
        public void Evaluate(ITradingObject tradingObject, Bar bar)
        {
            if (bar.Invalid())
            {
                return;
            }

            // remember the trading object and bar because the object could be used in AfterEvaulation
            _barsInPeriod.Add(tradingObject, bar);
            _codeToTradingObjectMap.Add(tradingObject.Code, tradingObject);

            // evaluate all components
            foreach (var component in _components)
            {
                component.Evaluate(tradingObject, bar);
            }

            string comments  = string.Empty;
            var    positions = _context.ExistsPosition(tradingObject.Code)
                ? _context.GetPositionDetails(tradingObject.Code)
                : (IEnumerable <Position>) new List <Position>();

            // decide if we need to exit market for this trading object. This is the first priorty work
            if (positions.Count() > 0)
            {
                foreach (var component in _marketExiting)
                {
                    if (component.ShouldExit(tradingObject, out comments))
                    {
                        _instructionsInCurrentPeriod.Add(
                            new Instruction()
                        {
                            Action         = TradingAction.CloseLong,
                            Comments       = "market exiting condition triggered. " + comments,
                            SubmissionTime = _period,
                            TradingObject  = tradingObject,
                            SellingType    = SellingType.ByVolume,
                            Volume         = positions.Sum(p => p.Volume),
                        });

                        return;
                    }
                }
            }

            // decide if we need to stop loss for some positions
            int totalVolume = 0;

            foreach (var position in positions)
            {
                if (position.StopLossPrice > bar.ClosePrice)
                {
                    totalVolume += position.Volume;
                }
            }

            if (totalVolume > 0)
            {
                _instructionsInCurrentPeriod.Add(
                    new Instruction()
                {
                    Action               = TradingAction.CloseLong,
                    Comments             = string.Format("stop loss @{0:0.000}", bar.ClosePrice),
                    SubmissionTime       = _period,
                    TradingObject        = tradingObject,
                    SellingType          = SellingType.ByStopLossPrice,
                    StopLossPriceForSell = bar.ClosePrice,
                    Volume               = totalVolume
                });

                return;
            }

            // decide if we should enter market
            if (positions.Count() == 0)
            {
                List <string> allComments = new List <string>(_marketEntering.Count + 1);
                allComments.Add("Entering market. ");

                bool canEnter = true;
                foreach (var component in _marketEntering)
                {
                    string subComments;

                    if (!component.CanEnter(tradingObject, out subComments))
                    {
                        canEnter = false;
                        break;
                    }

                    allComments.Add(subComments);
                }

                if (canEnter)
                {
                    CreateIntructionForBuying(tradingObject, bar.ClosePrice, string.Join(";", allComments));
                }
            }
        }