public override IEnumerable <Instruction> AdjustPositions() { var codes = Context.GetAllPositionCodes().ToArray(); var instructions = new List <Instruction>(); foreach (var code in codes) { var positions = Context.GetPositionDetails(code); if (positions.Count() != 1) { continue; } var position = positions.First(); if (position.LastedPeriodCount != 0) { continue; } var tradingObject = Context.GetTradingObject(code); var todayBar = Context.GetBarOfTradingObjectForCurrentPeriod(tradingObject); var dropPercentage = (todayBar.OpenPrice - todayBar.ClosePrice) / todayBar.OpenPrice * 100.0; if (dropPercentage > 0 && dropPercentage <= MaxDropPercentage) { var instruction = new OpenInstruction(CurrentPeriod, tradingObject, new TradingPrice(TradingPricePeriod.CurrentPeriod, TradingPriceOption.ClosePrice, 0.0)) { Comments = string.Format("Adjust: first day drop percentage {0:0.000}%", dropPercentage), Volume = position.Volume, StopLossGapForBuying = 0.0, StopLossPriceForBuying = position.StopLossPrice }; instructions.Add(instruction); } } return(instructions); }
public void NotifyTransactionStatus(Transaction transaction) { Instruction instruction; if (!_activeInstructions.TryGetValue(transaction.InstructionId, out instruction)) { throw new InvalidOperationException( string.Format("can't find instruction {0} associated with the transaction.", transaction.InstructionId)); } if (transaction.Action == TradingAction.OpenLong) { if (transaction.Succeeded) { // update the stop loss and risk for new positions var code = transaction.Code; if (!_context.ExistsPosition(code)) { throw new InvalidOperationException( string.Format("There is no position for {0} when calling this function", code)); } var positions = _context.GetPositionDetails(code); if (!positions.Any()) { throw new InvalidProgramException("Logic error"); } OpenInstruction openInstruction = instruction as OpenInstruction; // set stop loss and initial risk for all new positions if (positions.Count() == 1) { var position = positions.Last(); if (!position.IsStopLossPriceInitialized()) { position.SetStopLossPrice(openInstruction.StopLossPriceForBuying); _context.Log( string.Format( "Set stop loss for position {0}/{1} as {2:0.000}", position.Id, position.Code, openInstruction.StopLossPriceForBuying)); } } else { // set stop loss for positions created by PositionAdjusting component if (Math.Abs(openInstruction.StopLossPriceForBuying) > 1e-6) { var lastPosition = positions.Last(); var newStopLossPrice = openInstruction.StopLossPriceForBuying; // now set the new stop loss price for all positions foreach (var position in positions) { if (!position.IsStopLossPriceInitialized() || position.StopLossPrice < newStopLossPrice) { position.SetStopLossPrice(newStopLossPrice); _context.Log( string.Format( "PositionAdjusting:IncreaseStopLoss: Set stop loss for position {0}/{1} as {2:0.000}", position.Id, position.Code, newStopLossPrice)); } } } } } } // remove the instruction from active instruction collection. _activeInstructions.Remove(instruction.Id); }
public void EstimateStoplossAndSizeForNewPosition(Instruction instruction, double price, int totalNumberOfObjectsToBeEstimated) { OpenInstruction openInstruction = instruction as OpenInstruction; if (openInstruction == null) { return; } if (Math.Abs(openInstruction.StopLossPriceForBuying) > 1e-6) { return; } else if (Math.Abs(openInstruction.StopLossGapForBuying) > 1e-6) { openInstruction.StopLossPriceForBuying = price + openInstruction.StopLossGapForBuying; return; } else { foreach (var filter in _buyPriceFilters) { var filterResult = filter.IsPriceAcceptable(instruction.TradingObject, price); if (!filterResult.IsPriceAcceptable) { openInstruction.Comments = string.Join(" ", instruction.Comments, filterResult.Comments); openInstruction.Volume = 0; openInstruction.StopLossGapForBuying = 0.0; openInstruction.StopLossPriceForBuying = price; return; } else { price = filterResult.AcceptablePrice; } } var stopLossResult = _stopLoss.EstimateStopLossGap(instruction.TradingObject, price); if (stopLossResult.StopLossGap > 0.0) { throw new InvalidProgramException("the stop loss gap returned by the stop loss component is greater than zero"); } var stopLossGap = stopLossResult.StopLossGap; var positionSizingResult = _positionSizing.EstimatePositionSize(instruction.TradingObject, price, stopLossGap, totalNumberOfObjectsToBeEstimated); var volume = positionSizingResult.PositionSize; // adjust volume to ensure it fit the trading object's constraint volume -= volume % instruction.TradingObject.VolumePerBuyingUnit; openInstruction.Comments = string.Join(" ", instruction.Comments, stopLossResult.Comments); openInstruction.Comments = string.Join(" ", instruction.Comments, positionSizingResult.Comments); openInstruction.Volume = volume; openInstruction.StopLossGapForBuying = stopLossGap; openInstruction.StopLossPriceForBuying = price + stopLossGap; } }