Beispiel #1
0
        private void RunCurrentPeriodInstructions(
            Bar[] lastPeriodTradingData,
            Bar[] currentPeriodTradingData,
            DateTime time)
        {
            var readyInstructions = new List <Tuple <Instruction, double> >(_currentPeriodInstructions.Count);

            foreach (var instruction in _currentPeriodInstructions)
            {
                var tradingObjectIndex = instruction.TradingObject.Index;
                var currentBarOfObject = currentPeriodTradingData[tradingObjectIndex];

                if (currentBarOfObject.Time == Bar.InvalidTime)
                {
                    _context.Log(string.Format("the data for trading object {0} is invalid, can't execute instruction", instruction.TradingObject.Code));
                    continue;
                }

                // exclude 开盘涨停/跌停
                var          lastBarOfObject       = lastPeriodTradingData[tradingObjectIndex];
                const double MaxChangesCoefficient = 0.99;

                if (lastBarOfObject.Time != Bar.InvalidTime)
                {
                    if (instruction.Price.Option == TradingPriceOption.OpenPrice ||
                        instruction.Price.Option == TradingPriceOption.CustomPrice)
                    {
                        double priceChangeRatio = Math.Abs(currentBarOfObject.OpenPrice - lastBarOfObject.ClosePrice) / lastBarOfObject.ClosePrice;

                        if (instruction.Action == TradingAction.OpenLong &&
                            priceChangeRatio >= instruction.TradingObject.LimitUpRatio * MaxChangesCoefficient)
                        {
                            _context.Log(
                                string.Format(
                                    "{0} price {1:0.0000} hit limit up in {2:yyyy-MM-dd}, failed to execute transaction",
                                    instruction.TradingObject.Code,
                                    currentBarOfObject.OpenPrice,
                                    time));

                            continue;
                        }

                        if (instruction.Action == TradingAction.CloseLong &&
                            priceChangeRatio >= instruction.TradingObject.LimitDownRatio * MaxChangesCoefficient)
                        {
                            _context.Log(
                                string.Format(
                                    "{0} price {1:0.0000} hit limit down in {2:yyyy-MM-dd}, failed to execute transaction",
                                    instruction.TradingObject.Code,
                                    currentBarOfObject.OpenPrice,
                                    time));

                            continue;
                        }
                    }
                }

                // exclude 一字板
                if (currentBarOfObject.HighestPrice == currentBarOfObject.LowestPrice)
                {
                    if ((currentBarOfObject.LowestPrice < lastBarOfObject.ClosePrice &&
                         instruction.Action == TradingAction.CloseLong) ||
                        (currentBarOfObject.LowestPrice > lastBarOfObject.ClosePrice &&
                         instruction.Action == TradingAction.OpenLong))
                    {
                        _context.Log(
                            string.Format(
                                "{0} price is locked down in {1:yyyy-MM-dd}, failed to execute transaction",
                                instruction.TradingObject.Code,
                                time));
                    }

                    continue;
                }

                double price = CalculateTransactionPrice(
                    currentBarOfObject,
                    lastBarOfObject,
                    instruction);

                // Exclude unrealistic price.
                if ((_settings.IsLowestPriceAchievable && price < currentBarOfObject.LowestPrice) ||
                    (!_settings.IsLowestPriceAchievable && price <= currentBarOfObject.LowestPrice) ||
                    price > currentBarOfObject.HighestPrice)
                {
                    _context.Log(
                        string.Format(
                            "{0} price {1:0.000} in {2:yyyy-MM-dd} is not achievable",
                            instruction.TradingObject.Code,
                            price,
                            time));

                    continue;
                }

                readyInstructions.Add(Tuple.Create(instruction, price));
            }

            int totalNumberOfObjectsToBeEstimated = readyInstructions.Count(t => t.Item1.Action == TradingAction.OpenLong);
            int maxNewPositionCount = _strategy.GetMaxNewPositionCount(totalNumberOfObjectsToBeEstimated);

            var pendingTransactions = new List <Transaction>(readyInstructions.Count);

            foreach (var readyInstruction in readyInstructions)
            {
                var    instruction = readyInstruction.Item1;
                double price       = readyInstruction.Item2;

                if (instruction.Action == TradingAction.OpenLong)
                {
                    if (maxNewPositionCount <= 0)
                    {
                        _context.Log(string.Format(
                                         "Max new position count reached, ignore this instruction: {0}/{1}. //{2}",
                                         instruction.TradingObject.Code,
                                         instruction.TradingObject.Name,
                                         instruction.Comments));

                        continue;
                    }

                    _strategy.EstimateStoplossAndSizeForNewPosition(instruction, price, totalNumberOfObjectsToBeEstimated);
                    if (instruction.Volume == 0)
                    {
                        _context.Log(string.Format(
                                         "The volume of instruction for {0}/{1} is 0. //{2}",
                                         instruction.TradingObject.Code,
                                         instruction.TradingObject.Name,
                                         instruction.Comments));

                        continue;
                    }

                    --maxNewPositionCount;
                }

                var transaction = BuildTransactionFromInstruction(
                    instruction,
                    time,
                    price);

                pendingTransactions.Add(transaction);
            }

            // always execute transaction according to the original order, so the strategy itself
            // can decide the order.
            foreach (var transaction in pendingTransactions)
            {
                ExecuteTransaction(transaction, true);
            }

            // compact pending instruction list
            _currentPeriodInstructions.Clear();
        }