Примеры

Пример 1. Подключение к системе

  public async Task Connect(CancellationToken ct)
    {
         OtcConnectionSettings settings = new OtcConnectionSettings();
                
         OtcCredential cred = OtcCredential.Plain(<логин>, <пароль>);
         settings.EnableSignalRTracing = true;
         settings.EnableFeedMessageTracing = true;
         settings.Transports = DataFeedTransport.All;
         OtcEndpoint ep = new OtcEndpoint(<адрес полигона, например http://test.rtsboard.ru>);
         settings.Endpoint = ep;
         settings.Credential = cred;
         Connection = new OtcConnection(settings);            
         Connection.FeedConnectionStateChanged += Connection_FeedConnectionStateChanged;
         Connection.RestConnectionStateChanged += Connection_RestConnectionStateChanged;
         await Connection.ConnectAsync(ct);            
    }
    

Пример 2. Подключение к потокам рыночных данных

 async Task SubscribeFeeds(string subscribeString)
  {
    if (Subscriptions == null)
        Subscriptions = new Dictionary<string, IDisposable>();
    else
    {
        UnsubscribeFeeds();
        Subscriptions.Clear();
    }

    foreach (string s in _settings.EnabledFeeds.Split(';'))
    {
      //"PublicQuotes;OwnQuotes;FrontTrades;GenericTrades;Alerts";
      switch (s)
        {
         case "Quote":
           if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
           {
            Log.OtcInteraction.Warn("Подписка на поток публичных котировок с ролью BACKOFFICER может 
             привести к ошибкам в данных. Необходимо исправить конфигурацию");
           }
           SubscriptionListener<OTC.ClientAPI.Documents.Quotes.QuoteContract> pubQuotesListener 
            = new SubscriptionListener<OTC.ClientAPI.Documents.Quotes.QuoteContract>(ProcessPublicQuoteRecord,s);
                
           OTC.ClientAPI.DataFeed.ISubscription<OTC.ClientAPI.Documents.Quotes.QuoteContract> pq 
            = await Connection.Quotes.SubscribeToPublicQuotesAsync(pubQuotesListener, s, null);
                
           Subscriptions.Add(s, pq);
         break;
         case "OwnQuote":
            if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
             {
              Log.OtcInteraction.Warn("Подписка на поток собственных котировок с ролью BACKOFFICER может 
               привести к ошибкам в данных. Необходимо исправить конфигурацию");
             }
            SubscriptionListener<OTC.ClientAPI.Documents.Quotes.QuoteContract> ownQuotesListener 
              = new SubscriptionListener<OTC.ClientAPI.Documents.Quotes.QuoteContract>(ProcessOwnQuoteRecord, s);
                
            OTC.ClientAPI.DataFeed.ISubscription<OTC.ClientAPI.Documents.Quotes.QuoteContract> oq 
               = await Connection.Quotes.SubscribeToOwnQuotesAsync(ownQuotesListener, s, null);
                
             Subscriptions.Add(s, oq);
         break;
         case "MarketTrade":
           if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
              {
               Log.OtcInteraction.Warn("Подписка на поток рыночных сделок с ролью BACKOFFICER может 
               привести к ошибкам в данных. Необходимо исправить конфигурацию");
              }
             MarketTrade trade = db.GetMaxValueRecord<MarketTrade>("TradeDate", "MarketTrade");
             OTC.ClientAPI.Documents.MarketTrades.FilterParameters filter = new OTC.ClientAPI.Documents.MarketTrades.FilterParameters();
                
           if (trade != null)
              {
                DatetimeRange dtr = new DatetimeRange();
                dtr.From = trade.TradeDate;
                filter.Date = dtr;
              }
           else
            {
              filter = null;
             }
              SubscriptionListener<OTC.ClientAPI.Documents.MarketTrades.MarketTradeContract> marketTradesListener 
               = new SubscriptionListener<OTC.ClientAPI.Documents.MarketTrades.MarketTradeContract>(ProcessMarketTradeRecord, s);
                
               OTC.ClientAPI.DataFeed.ISubscription<OTC.ClientAPI.Documents.MarketTrades.MarketTradeContract> mt 
               = await Connection.MarketTrades.SubscribeAsync(marketTradesListener, s, filter);
                
               Subscriptions.Add(s, mt);
         break;
         case "GenericTrade":
                
          SubscriptionListener<OTC.ClientAPI.Documents.GenericTrades.GenericTradeContract> genericTradesListener 
          = new SubscriptionListener<OTC.ClientAPI.Documents.GenericTrades.GenericTradeContract>(ProcessGenericTradeRecord, s);
                
            OTC.ClientAPI.DataFeed.ISubscription<OTC.ClientAPI.Documents.GenericTrades.GenericTradeContract> gt = 
            await Connection.GenericTrades.SubscribeAsync(genericTradesListener, s, null);
            Subscriptions.Add(s, gt);                        
         break;
        }
    }          
}

Пример 3. Обработка потока GenericTrade

 async Task GenericTradeProcessing(OTC.ClientAPI.Documents.GenericTrades.GenericTradeContract data, string recID)
  {
    switch (data.State.Split(':')[0])
    {
        case "FRONT":
            if (_settings.ConnectionType == OtcConnectionType.TRADER)
            {
                try
                {
                    OTC.ClientAPI.Documents.Extensions.GetDocumentResponse<OTC.ClientAPI.Documents.FrontTrades.FrontTradeContract> f 
                        = await Connection.FrontTrades.GetAsync(data.ActiveId);
                    if (f.Success)
                    {
                        FrontTrade ft = QuatroMapping.GetObject<FrontTrade>(f.Document);
                        db.OnAddOrUpdate<FrontTrade>(ft, ft.Id);
                    }
                }
                catch (ApiErrorException e)
                {

                }
            }                    
        break;
        case "MIDDLE":
            if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
            {
                try
                {
                  OTC.ClientAPI.Documents.Extensions.GetDocumentResponse<OTC.ClientAPI.Documents.MiddleTrades.MiddleTradeContract> m
                        = await Connection.MiddleTrades.GetAsync(data.ActiveId);
                    if (m.Success)
                    {
                        MiddleTrade mt = QuatroMapping.GetObject<MiddleTrade>(m.Document);
                        db.OnAddOrUpdate<MiddleTrade>(mt, mt.Id);
                    }
                }
                catch (ApiErrorException e)
                {

                }
            }
        break;
        case "BACK":
            if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
            {
                try
                {
                    OTC.ClientAPI.Documents.Extensions.GetDocumentResponse<OTC.ClientAPI.Documents.BackTrades.BackTradeContract> b
                        = await Connection.BackTrades.GetAsync(data.ActiveId);
                    if (b.Success)
                    {
                        BackTrade bt = QuatroMapping.GetObject<BackTrade>(b.Document);
                        db.OnAddOrUpdate<BackTrade>(bt, bt.Id);
                    }
                }
                catch (ApiErrorException e)
                { }
            }
        break;
        case "FINAL":
            if (_settings.ConnectionType == OtcConnectionType.BACKOFFICER)
            {
                try
                {
                    OTC.ClientAPI.Documents.Extensions.GetDocumentResponse<OTC.ClientAPI.Documents.FinalTrades.FinalTradeContract> f
                        = await Connection.FinalTrades.GetAsync(data.ActiveId);
                    if (f.Success)
                    {
                        FinalTrade ft = QuatroMapping.GetObject<FinalTrade>(f.Document);
                        db.OnAddOrUpdate<FinalTrade>(ft, ft.Id);
                    }
                    else
                    {
                    }
                }
                catch (ApiErrorException e)
                {

                }
            }
        break;
    }
  }

Пример 4. Формирование контента документов

public struct TransactionDefinition
  {
    public decimal? Price; 
    public int? Qty;
    public string Direction;
    public DateTime? SettlDate;
    public DateTime? DeliveryDate;
    public string PriceCurrency;
    public string SettlCurrency;
    public string DeliveryMethod;
    public bool isFrontOffice; 
  }


 public static string MakeSecurityQuoteContent( TransactionDefinition td, Instrument i)
  {
    string tranType = string.Empty;
    string instrumentType = string.Empty;

    switch (i.ClassId)
    {
        case "stocks":
            tranType = "equityTransaction";
            instrumentType = "equity";

            break;
        case "bonds":
            tranType = "bondTransaction";
            instrumentType = "bond";

            break;
        default:
            tranType = "equityTransaction";
            instrumentType = "equity";
            break;
    }

    XElement root = new XElement(rtsotc + tranType,
        new XAttribute(XNamespace.Xmlns + "fpml", fpml),
        new XAttribute(XNamespace.Xmlns + "rtsrep", rtsrep),
        new XAttribute(XNamespace.Xmlns + "fpmlext", fpmlext),
        new XAttribute(XNamespace.Xmlns + "dsig", ds),
        new XAttribute(XNamespace.Xmlns + "rtsotc", rtsotc)
       );

    XDocument doc = new XDocument(root);

    string buyerRef = "party1";
    string sellerRef = "party2";

    if (td.isFrontOffice)
    {
        buyerRef = (td.Direction.ToUpper() == "BUY") ? "quote-owner" : "counterparty";
        sellerRef = (td.Direction.ToUpper() == "BUY") ? "counterparty" : "quote-owner";
    }
    else
    {
        buyerRef = (td.Direction.ToUpper() == "BUY") ? "party1" : "party2";
        sellerRef = (td.Direction.ToUpper() == "BUY") ? "party2" : "party1";

    }

    root.Add(new XElement(fpml + "buyerPartyReference", new XAttribute("href", buyerRef)));
    root.Add(new XElement(fpml + "sellerPartyReference", new XAttribute("href", sellerRef)));
    root.Add(new XElement(rtsotc + "issuingVolumes", (i.IssuingVolume.HasValue) ? i.IssuingVolume.Value.ToString() : string.Empty));
    root.Add(new XElement(rtsotc + "numberOfUnits", (td.Qty.HasValue) ? td.Qty.Value.ToString() : string.Empty));
    root.Add(new XElement(rtsotc + "unitPrice", (td.Price.HasValue) ? GetStringNumber(td.Price.Value) : string.Empty));
    root.Add(new XElement(rtsotc + "priceCurrency", td.PriceCurrency));

    //блок идентификации инструмента
    XElement instrumentDefinition = new XElement(rtsotc + instrumentType);
    instrumentDefinition.Add(new XElement(fpml + "instrumentId", new XAttribute("instrumentIdScheme", 
        "http://www.fpml.ru/coding-scheme/instrument-id#code"), i.Id));
    instrumentDefinition.Add(new XElement(fpml + "instrumentId", new XAttribute("instrumentIdScheme", 
        "http://www.fpml.ru/coding-scheme/instrument-id#regnum"), i.Regnum));
    instrumentDefinition.Add(new XElement(fpml + "instrumentId", new XAttribute("instrumentIdScheme", 
        "http://www.fpml.ru/coding-scheme/instrument-id#cfi"), i.CFI));
    instrumentDefinition.Add(new XElement(fpml + "instrumentId", new XAttribute("instrumentIdScheme", 
        "http://www.fpml.ru/coding-scheme/instrument-id#isin"), i.ISIN));
    instrumentDefinition.Add(new XElement(fpml + "description", i.NameRu));
    instrumentDefinition.Add(new XElement(fpml + "currency", i.Currency));
    instrumentDefinition.Add(new XElement(fpml + "exchangeId", i.ExchangeId));
    root.Add(instrumentDefinition);

    root.Add(new XElement(rtsotc + "unitNotional", GetStringNumber(i.UnitNominal)));
    root.Add(new XElement(rtsotc + "deliveryMethod", td.DeliveryMethod));
    root.Add(new XElement(rtsotc + "settlementDate", (td.SettlDate.HasValue) ? td.SettlDate.Value.ToString("yyyy-MM-dd") : string.Empty));
    root.Add(new XElement(rtsotc + "deliveryDate", (td.DeliveryDate.HasValue) ? td.DeliveryDate.Value.ToString("yyyy-MM-dd") : string.Empty));
    root.Add(new XElement(rtsotc + "settlementCurrency", td.SettlCurrency));

    return root.ToString(SaveOptions.None);
  }

Пример 5. Создание котировки

/// <summary>
  /// Создание собственной котировки
  /// </summary>
  /// <param name="InstrId">Идентификатор инструмента</param>
  /// <param name="Price">Цена</param>
  /// <param name="Qty">Количество</param>
  /// <param name="direction">Направление (b-BUY, s-SELL)</param>
  /// <returns>Структурированный результат выполнения действия</returns>
  public async Task<DocumentData> CreateQuote(string InstrId, decimal Price, int Qty, string direction)
  {
    OTC.ClientAPI.Accounts.GetResponse acc=await Connection.Accounts.GetCurrentAsync(_settings.Login);
    if (!acc.Success)
    {
        Log.OtcInteraction.Info("Невозможно получить данные об аккаунте для логина {0}", _settings.Login);
        return new DocumentData() { Error = string.Format("Невозможно получить данные об аккаунте для логина {0}", _settings.Login) };
    }
    
    
    OTC.ClientAPI.Documents.Quotes.QuoteContract q = new OTC.ClientAPI.Documents.Quotes.QuoteContract();
    q.Comment = "Autogenerated";
    q.DeliveryDate = DateTime.Now.AddDays(4d);
    q.DeliveryMethod = "DeliveryVersusPayment";
    q.Direction = (direction.ToUpper() == "B") ? OTC.ClientAPI.Documents.Quotes.OperationDirectionContract.Buy : 
        OTC.ClientAPI.Documents.Quotes.OperationDirectionContract.Sell;
    q.Instrument=InstrId;            
    q.IsDynamic=false;
    q.IsIndicative=false;
    q.IsTargeted=false;
    q.PartyId = acc.Account.PartyId;
    q.Price = Price;
    q.PriceCurrencyId = "USD";
    q.Quantity = Qty;
    q.SettlementCurrencyId = "USD";
    q.SettlementDate = DateTime.Now.AddDays(4d);
    q.TimeToLive = OTC.ClientAPI.Documents.Quotes.QuoteTimeToLiveContract.GoodTillCancelled;
    Instrument i = db.GetRecord<Instrument>(q.Instrument);
    q.Content=ContentBuilder.MakeSecurityQuoteContent(q,i);

    //создание черновика котировки
    OTC.ClientAPI.Documents.Extensions.CreateDocumentResponse<OTC.ClientAPI.Documents.Quotes.QuoteContract> x
        = await Connection.Quotes.CreateAsync(q);
    if (x.Success)
    {
       
        Log.OtcInteraction.Info("Котировка {0}/{1}/{2} отправлена успешно", InstrId, Price, Qty);
        //и активирование его в системе
        return await SendQuote(x.Document.Id, x.Document.Revision);
        
    }
    else
    {
        Log.OtcInteraction.Info("Ошибка при отправке котировки {0}/{1}/{2}", InstrId, Price, Qty);
        return new DocumentData() { Id = string.Empty, Rev = 0, Error = x.Errors.DocumentError.Message.Ru };
    }
  }

Пример 6. Создание договора бэк-офиса

/// <summary>
  /// Создание нового догоовра бэк-офиса
  /// </summary>
  /// <param name="price">Цена</param>
  /// <param name="qty">Количество</param>
  /// <param name="direction">Направление (b-BUY, s-SELL)</param>
  /// <param name="instrId">Тикер инструмента</param>
  /// <param name="party2Id">Идентификатор контрагента</param>
  /// <param name="clientId">Идентификатор клиента</param>
  /// <param name="settlSchemeId">Идентификатор расчетной схемы</param>
  /// <returns>Структурированный результат выполнения действия</returns>
  public async Task<DocumentData> CreateBackTrade(decimal price, int qty, string direction, string instrId, 
    string party2Id, int? clientId, int settlSchemeId)
  {

    OTC.ClientAPI.Accounts.GetResponse acc = await Connection.Accounts.GetCurrentAsync(_settings.Login);
    if (!acc.Success)
    {
        Log.OtcInteraction.Info("Невозможно получить данные об аккаунте для логина {0}", _settings.Login);
        return new DocumentData() { Error = string.Format("Невозможно получить данные об аккаунте для логина {0}", _settings.Login) };
    }

    OTC.ClientAPI.Documents.BackTrades.BackTradeContract contract = new OTC.ClientAPI.Documents.BackTrades.BackTradeContract();
    contract.AdditionalTerms = "NONE";
    contract.Comment = "Autogenerated";
    TransactionDefinition def = new TransactionDefinition()
    {
        Price = price,
        Qty = qty,
        Direction = (direction.ToUpper()=="B")? "Buy":"Sell",
        isFrontOffice = false,
        PriceCurrency = "USD",
        SettlCurrency = "USD",
        SettlDate = DateTime.Now.AddDays(4),
        DeliveryDate = DateTime.Now.AddDays(4),
        DeliveryMethod = "DeliveryVersusPayment"
    };
    Instrument i = db.GetRecord<Instrument>(instrId);
    contract.Content = ContentBuilder.MakeSecurityQuoteContent(def, i);
    contract.CheckLimits = false;
    contract.DeliveryDate = def.DeliveryDate;
    contract.DeliveryMethod = def.DeliveryMethod;
    contract.ExchangeRate = null;
    contract.ExternalTradeIdentifier1 = Guid.NewGuid().ToString();
    contract.InstrumentId = i.Id;
    contract.IsPublic = false;
    
    if (clientId.HasValue)
    {
        Client c = db.GetRecord<Client>(clientId);
        contract.Party1ClientCode = c.Name;
        contract.Party1ClientRelation = "AgentAgreement";
        contract.Party1ClientRelationBasis = "Некоторое основание";
    }
    contract.Party1Id = acc.Account.PartyId;
    contract.Party2Id = party2Id;
    contract.Price = def.Price;
    contract.PriceCurrencyId = def.PriceCurrency;
    contract.Quantity = def.Qty;
    contract.SecuritiesTransferParty = "SettlementDepository";
    contract.SettlementCurrencyId = def.SettlCurrency;
    contract.SettlementDate = def.SettlDate;

    OTC.ClientAPI.SettlementSchemes.Schemes.GetResponse settlScheme = await Connection.SettlementSchemes.GetAsync(settlSchemeId, 1);
    if (settlScheme.Success)
    {
        contract.Party1SettlementSchemeXml = settlScheme.SettlementScheme.Body;
    }
   
    OTC.ClientAPI.Documents.Extensions.CreateDocumentResponse<OTC.ClientAPI.Documents.BackTrades.BackTradeContract> result
        = await Connection.BackTrades.CreateAsync(contract);
    if (result.Success)
    {
        return new DocumentData()
        {
            Id = result.Document.Id,
            Rev = result.Document.Revision,
            State = result.Document.State.Id
        };
    }
    return new DocumentData();
  }