public OptionData(OptionData op) { Type = op.Type; Style = op.Style; BaseActive = op.BaseActive; DatePublished = op.DatePublished; DateExpiration = op.DateExpiration; StrikePrice = op.StrikePrice; ContractHigh = op.ContractHigh; ContractLow = op.ContractLow; ContractClose = op.ContractClose; OpenInterest = op.OpenInterest; Volume = op.Volume; }
public bool Equals(OptionData op) { if (op == null) return false; return Type == op.Type && Style == op.Style && BaseActive == op.BaseActive && DatePublished == op.DatePublished && DateExpiration == op.DateExpiration && StrikePrice == op.StrikePrice && ContractHigh == op.ContractHigh && ContractLow == op.ContractLow && ContractClose == op.ContractClose && OpenInterest == op.OpenInterest && Volume == op.Volume; }
/// <summary> /// Формат строки "[#fmt]#;newstype=option#;type=val#;style=val#;baseactive=val#;countdate=val#; /// dateexpiration=val#;strikeprice=val#;delta=val#;openinterest=val" /// </summary> /// <param name="op"></param> public static OptionData Parse(String op) { var od = new OptionData(); try { var separator = new[] { PartsSeparator }; var str = op.Split(separator, StringSplitOptions.RemoveEmptyEntries); if (str.Length != 13) return null; if (str[0] != "[#fmt]") return null; // строка отформатирована, проверим, что это опцион var members = new Dictionary<string, string>(); var sep = new [] { '=' }; foreach (var a in str) { var mem = a.Split(sep); if (mem.Count() == 1) continue; members.Add(mem[0], mem[1]); } if (members["newstype"] == null || members["newstype"] != "option") throw new Exception("OptionData.Parse: тип новости отличается от опциона"); var typeStr = members["type"]; if (!string.IsNullOrEmpty(typeStr)) od.Type = (OptionType)Enum.Parse(typeof(OptionType), typeStr); var styleStr = members["style"]; if (!string.IsNullOrEmpty(styleStr)) od.Style = (OptionStyle)Enum.Parse(typeof(OptionStyle), styleStr); od.BaseActive = members["baseactive"]; od.DatePublished = members["publishdate"].ToDateTimeUniform(); od.DateExpiration = DateTime.ParseExact(members["dateexpiration"], "dd.MM.yyyy", CultureProvider.Common); od.StrikePrice = members["strikeprice"].ToFloatUniform(); od.ContractHigh = members["high"].ToFloatUniform(); od.ContractLow = members["low"].ToFloatUniform(); od.ContractClose = members["close"].ToFloatUniform(); od.OpenInterest = members["oi"].ToInt(); od.Volume = members["volume"].ToInt(); } catch (InvalidCastException ex) { Logger.Error("OptionData.Parse ошибка ", ex); return null; } catch (Exception ex) { Logger.Error("OptionData.Parse ошибка ", ex); return null; } return od; }
private void BuildSummaryOL() { if (options.Count == 0) return; // count date - level * [OI | Volume], sum OI, sum Volume var dicSumCall = new Dictionary<DateTime, Cortege3<float, float, float>>(); var dicSumPut = new Dictionary<DateTime, Cortege3<float, float, float>>(); foreach (var opt in options) { if ((AllowedOptionStyles == AllowedOptionStyle.American && opt.Style == OptionStyle.European) || (AllowedOptionStyles == AllowedOptionStyle.European && opt.Style == OptionStyle.American)) continue; var multiplier = WeightType == OptionLevelWeightType.ОткрытыйИнтерес ? opt.OpenInterest : opt.Volume; if (opt.Type == OptionType.CALL) { var sumCall = opt.OptionLevelClose*multiplier; if (!dicSumCall.ContainsKey(opt.DatePublished)) dicSumCall.Add(opt.DatePublished, new Cortege3<float, float, float>(sumCall, opt.OpenInterest, opt.Volume)); else { sumCall += dicSumCall[opt.DatePublished].a; var totalOI = dicSumCall[opt.DatePublished].b + opt.OpenInterest; var totalVolume = dicSumCall[opt.DatePublished].c + opt.Volume; dicSumCall[opt.DatePublished] = new Cortege3<float, float, float>(sumCall, totalOI, totalVolume); } } else { var sumPut = opt.OptionLevelClose*multiplier; if (!dicSumPut.ContainsKey(opt.DatePublished)) dicSumPut.Add(opt.DatePublished, new Cortege3<float, float, float>(sumPut, opt.OpenInterest, opt.Volume)); else { sumPut += dicSumPut[opt.DatePublished].a; var totalOI = dicSumPut[opt.DatePublished].b + opt.OpenInterest; var totalVolume = dicSumPut[opt.DatePublished].c + opt.Volume; dicSumPut[opt.DatePublished] = new Cortege3<float, float, float>(sumPut, totalOI, totalVolume); } } } var sumOpts = new List<OptionData>(); foreach (var date in dicSumCall) { if (date.Value.a == 0) continue; var strike = date.Value.a/(WeightType == OptionLevelWeightType.ОткрытыйИнтерес ? date.Value.b : date.Value.c); var opt = new OptionData(OptionType.CALL, OptionStyle.American, options[0].BaseActive, date.Key, new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1), strike, 0, 0, 0, (int) date.Value.b, (int) date.Value.c); sumOpts.Add(opt); } foreach (var date in dicSumPut) { if (date.Value.a == 0) continue; var strike = date.Value.a/(WeightType == OptionLevelWeightType.ОткрытыйИнтерес ? date.Value.b : date.Value.c); var opt = new OptionData(OptionType.PUT, OptionStyle.American, options[0].BaseActive, date.Key, new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1), strike, 0, 0, 0, (int) date.Value.b, (int) date.Value.c); sumOpts.Add(opt); } // медианный уровень List<Cortege2<DateTime, float>> channelCall = null, channelPut = null, channelMid = null; if (SummaryLevelStyle == SummaryLevelLineStyle.Каналы) { channelCall = new List<Cortege2<DateTime, float>>(); channelPut = new List<Cortege2<DateTime, float>>(); channelMid = new List<Cortege2<DateTime, float>>(); } foreach (var callData in dicSumCall) { if (!dicSumPut.ContainsKey(callData.Key)) continue; var putData = dicSumPut[callData.Key]; var oi = callData.Value.b + putData.b; var volume = callData.Value.c + putData.c; var denominator = WeightType == OptionLevelWeightType.ОткрытыйИнтерес ? oi : volume; var strike = (callData.Value.a + putData.a)/denominator; var opt = new OptionData(WeightType == OptionLevelWeightType.ОткрытыйИнтерес ? callData.Value.b > putData.b ? OptionType.CALL : OptionType.PUT : callData.Value.c > putData.c ? OptionType.CALL : OptionType.PUT, OptionStyle.American, options[0].BaseActive, callData.Key, new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1), strike, 0, 0, 0, (int) oi, (int) volume); // добавить мед. уровень if (SummaryLevelStyle == SummaryLevelLineStyle.Каналы) channelMid.Add(new Cortege2<DateTime, float>( opt.DatePublished, opt.OptionLevelClose)); else AddOptionLevel(opt, true); } foreach (var opt in sumOpts) { if (SummaryLevelStyle == SummaryLevelLineStyle.Каналы) { var pivot = new Cortege2<DateTime, float>(opt.DatePublished, opt.OptionLevelClose); if (opt.Type == OptionType.CALL) channelCall.Add(pivot); else channelPut.Add(pivot); } else AddOptionLevel(opt, false); } // построить каналы a-la Bollinger? if (SummaryLevelStyle == SummaryLevelLineStyle.Каналы) { BuildLineSeriesFromPivots(channelCall, seriesChannelCall); BuildLineSeriesFromPivots(channelPut, seriesChannelPut); BuildLineSeriesFromPivots(channelMid, seriesChannelMid); } }
private void AddOptionLevel(OptionData opt, bool isMedian) { var color = isMedian ? Color.Green : opt.Type == OptionType.PUT ? colorPut : colorGet; var linePart = new SpanWithText { Price = opt.OptionLevelClose, LineColor = color, Name = string.Format("{0} {1:f4} OI:{2}", opt.Type, opt.OptionLevelClose, opt.OpenInterest) }; var indexStart = owner.StockSeries.GetIndexByCandleOpen(opt.DatePublished); var indexEnd = owner.StockSeries.GetIndexByCandleOpen(opt.DatePublished.AddHours(LengthHours)); // проверить расстояние до рынка в пп // как мин. расстояние до уровня if (MaxPointsDistanceToShow > 0) { var candles = owner.StockSeries.Data.Candles; var distanceAbs = float.MaxValue; for (var i = indexStart < 0 ? 0 : indexStart; i < indexEnd; i++) { if (i >= candles.Count) break; var dist = Math.Min( Math.Abs(candles[i].high - opt.OptionLevelClose), Math.Abs(candles[i].low - opt.OptionLevelClose)); if (dist < distanceAbs) distanceAbs = dist; } var distPoints = DalSpot.Instance.GetPointsValue(owner.Symbol, distanceAbs); if (distPoints > MaxPointsDistanceToShow) return; } linePart.StartIndex = indexStart; linePart.EndIndex = indexEnd; var daysLeft = (opt.DateExpiration - opt.DatePublished).TotalDays; if (daysLeft <= daysToHighlight) linePart.LineWidth = 2; // показать метки if (LabelLeft != LevelLabel.Нет) AddOptionLabel(linePart, LabelLeft, true, opt); if (LabelRight != LevelLabel.Нет) AddOptionLabel(linePart, LabelRight, false, opt); seriesSpan.data.Add(linePart); // подсказка по уровню lineHints.Add(linePart, string.Format("{0:f4}{1} {2} (strike:{3:f4} close:{4:f4} OI:{5} volm:{6})", opt.OptionLevelClose, opt.Type, opt.Style == OptionStyle.American ? "AM" : "EU", opt.StrikePrice, opt.ContractClose, opt.OpenInterest, opt.Volume)); }
private static void AddOptionLabel(SpanWithText span, LevelLabel label, bool isLeft, OptionData opt) { string text = label == LevelLabel.Объем ? opt.Volume.ToString() : label == LevelLabel.ОткрИнтерес ? opt.OpenInterest.ToString() : string.Format("{0:MMMyy}", opt.DateExpiration); if (isLeft) span.TextLeft = text; else span.TextRight = text; }