private void OnNewRatesEvent(RateRecord rec, Candle candle) { SendNewRatesEvent(rec, candle); _strategyController.ProcessTick(rec); _orderController.CloseOrdersByLimits(rec); }
//send events private void SendNewRatesEvent(RateRecord rec, Candle candle) { if (NewRatesEvent != null) { _asyncOperation.Post(delegate { NewRatesEvent(rec, candle); }, null); } }
private void SendNewRatesEvent(RateRecord rec, Candle candle) { if (NewRatesEvent != null) { NewRatesEvent(rec, candle); } }
private void OnNewRates(RateRecord rec, Candle candle) { try { if (rec != null) { if (_currentRates.Keys.Contains(rec.Name)) { _currentRates[rec.Name] = rec.Value; } else { _currentRates.Add(rec.Name, rec.Value); } tbCurrentRates.Text = ""; foreach (string key in _currentRates.Keys) { tbCurrentRates.Text += string.Format("{0} - {3:dd-MM-yyyy HH-mm-ss} - {1}{2}", key, _currentRates[key], Environment.NewLine, rec.UpdateTime); } } DisplayCandle(candle); } catch (Exception ex) { OnMessage(ex.Message); } }
public IList <RateRecord> GetRates() { List <RateRecord> result = new List <RateRecord>(); NameValueCollection nvc = new NameValueCollection(); nvc.Add("Key", KEY); PostSubmitter post = new PostSubmitter(CURRENT_RATES_URL, nvc); post.Type = PostSubmitter.PostTypeEnum.Post; string resp = post.Post(); MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(resp.ToCharArray())); DataSet ds = new DataSet(); ds.ReadXml(ms); for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { RateRecord rt = new RateRecord(); rt.Name = ds.Tables[0].Rows[i]["Quote"].ToString(); string strRate = ds.Tables[0].Rows[i]["Display"].ToString().Substring(0, ds.Tables[0].Rows[i]["Display"].ToString().IndexOf('/')); rt.Value = decimal.Parse(strRate); object dt = ds.Tables[0].Rows[i]["UpdateTime"]; DateTime updateTime = Convert.ToDateTime(dt).ToUniversalTime(); rt.UpdateTime = updateTime; result.Add(rt); } return(result); }
public IStrategyDecision GetStrategyDecision(RateRecord rec) { DateTime date = rec.UpdateTime; decimal price = rec.Value; IDictionary <DateTime, decimal> historyData = _historyData[rec.Name]; if (!historyData.Keys.Contains(date)) { historyData.Add(date, price); } //return TestAnalize(historyData); decimal lastValue = StrategyHelper.GetLastValue(historyData); decimal decrease = StrategyHelper.GetMaximum(INTERVAL_MINUTES, historyData) - lastValue; decimal increase = lastValue - StrategyHelper.GetMinimum(INTERVAL_MINUTES, historyData); decimal largeMedium = (StrategyHelper.GetMaximum(LARGE_MEDIUM_INTERVAL_MINUTES, historyData) + StrategyHelper.GetMinimum(LARGE_MEDIUM_INTERVAL_MINUTES, historyData)) / 2; int momentDirection = 0; if (decrease > MAX_DIRECTION) { momentDirection = -1; } if (increase > MAX_DIRECTION) { momentDirection = 1; } int longDirection = 0; if (lastValue > largeMedium) { longDirection = 1; } if (lastValue < largeMedium) { longDirection = -1; } int result = 0; if (momentDirection == -1 && longDirection == +1) { result = 1; } if (momentDirection == 1 && longDirection == -1) { result = -1; } BaseStrategyDecision decision = new BaseStrategyDecision(); decision.TakeProfit = lastValue + (TAKE_PROFIT_POINTS * result); decision.StopLoss = lastValue - (STOP_LOSS_POINTS * result); StringBuilder additionalInfo = new StringBuilder(); additionalInfo.AppendFormat("Максимальное изменение за две минуты:{0}", (decrease > increase ? decrease : increase) * momentDirection); additionalInfo.AppendFormat("Текущее отклонение от среднего за 30 минут:{0}", lastValue - largeMedium); return(decision); }
public void ProcessTick(RateRecord rateRecord) { foreach (IStrategyProvider provider in _strategyProviders) { //analize IStrategyDecision decision = provider.GetStrategyDecision(rateRecord); //make orders OpenOrCloseOrders(provider.GetName(), decision, rateRecord); } }
public void CloseOrdersByLimits(RateRecord rec) { for (int i = _openedOrders.Count - 1; i >= 0; i--) { Order order = _openedOrders[i]; if (rec.Name != order.RateName) { continue; } if (order.Direction < 0 && (order.StopLoss < rec.Value || order.TakeProfit > rec.Value)) { CloseOrder(order, rec); } if (order.Direction > 0 && (order.StopLoss > rec.Value || order.TakeProfit < rec.Value)) { CloseOrder(order, rec); } } }
public void CloseOrder(Order order, RateRecord rec) { if (order.RateName != rec.Name) { return; } order.ClosePrice = rec.Value; order.CloseTime = rec.UpdateTime; if (order.IsReal) { order.IsReal = _enableRealOrders = StartFx.CloseOrder(order.RateName); } UpdateStrategyResult(order); if (CloseOrderEvent != null) { CloseOrderEvent(order); } _openedOrders.Remove(order); }
public static void CloseCandle(IDictionary <string, IList <Candle> > candles, RateRecord rec, int candlesIintervalMinutes) { if (!candles.ContainsKey(rec.Name)) { candles.Add(rec.Name, new List <Candle>()); } DateTime openCandleDate = new DateTime(rec.UpdateTime.Year, rec.UpdateTime.Month, rec.UpdateTime.Day, rec.UpdateTime.Hour, (rec.UpdateTime.Minute / candlesIintervalMinutes) * candlesIintervalMinutes, 0); DateTime closeCandleDate = new DateTime(rec.UpdateTime.Year, rec.UpdateTime.Month, rec.UpdateTime.Day, rec.UpdateTime.Hour, (rec.UpdateTime.Minute / candlesIintervalMinutes) * candlesIintervalMinutes, 0).AddMinutes(candlesIintervalMinutes); Candle currentCandle = candles[rec.Name].Where(item => item.OpenTime == openCandleDate).FirstOrDefault(); if (currentCandle == null) { ClosePreviousCandles(candles[rec.Name].Where(item => item.CandleData != null).ToList()); currentCandle = new Candle(); currentCandle.RateName = rec.Name; currentCandle.OpenTime = openCandleDate; candles[rec.Name].Add(currentCandle); } currentCandle.AddNewData(rec.UpdateTime, rec.Value); }
private void MainThread() { if (_rates.Count == 0) { SendMessageEvent("Невыбрано ни одной валютной пары!"); _shouldStop = true; } Dictionary <string, DateTime> lastProcessedDates = new Dictionary <string, DateTime>(); if (!_shouldStop) { IDictionary <string, IDictionary <DateTime, decimal> > ratesHistory = GetRatesHistory(_rates, _dtStart.AddHours(-4), _dtStart); _candles = StrategyHelper.BuildCandles(ratesHistory, RateController.CANDLES_INTERVAL_MINUTES); if (HistoryEvent != null) { HistoryEvent(ratesHistory, _candles); } foreach (string rateName in _rates) { if (ratesHistory[rateName].Count == 0) { lastProcessedDates.Add(rateName, _dtStart); } else { lastProcessedDates.Add(rateName, ratesHistory[rateName].Keys.Max()); } } } while (!_shouldStop) { //читаем котировки из интернета IDictionary <string, IDictionary <DateTime, decimal> > ratesCache; IDictionary <string, IList <Candle> > candlesCache; if (_dtEnd == null) { ratesCache = GetCurrentRates(_rates); candlesCache = GetCurrentCandles(_rates); } else { ratesCache = GetRatesHistory(_rates, lastProcessedDates.Values.Min().AddSeconds(1), lastProcessedDates.Values.Min().AddHours(2)); candlesCache = StrategyHelper.BuildCandles(ratesCache, CANDLES_INTERVAL_MINUTES); } //обрабатываем котировки по каждой валютной паре foreach (string rateName in _rates) { if (_shouldStop) { break; } if (!ratesCache.ContainsKey(rateName)) { continue; } IDictionary <DateTime, decimal> rateCache = ratesCache[rateName]; IList <Candle> candleCache = candlesCache[rateName]; while (rateCache.Count > 0 && rateCache.Keys.Min() > lastProcessedDates[rateName] && !_shouldStop) { RateRecord rec = new RateRecord(); rec.Name = rateName; rec.UpdateTime = rateCache.Keys.Min(); rec.Value = rateCache[rec.UpdateTime]; Candle candle = candlesCache[rateName].Where(item => item.OpenTime < rec.UpdateTime && rec.UpdateTime < item.OpenTime.AddMinutes(RateController.CANDLES_INTERVAL_MINUTES)).FirstOrDefault(); SendNewRatesEvent(rec, candle); rateCache.Remove(rec.UpdateTime); candlesCache[rateName].Remove(candle); lastProcessedDates[rateName] = rec.UpdateTime; } } if (_dtEnd != null && lastProcessedDates.Values.Min() > _dtEnd) { break; } Thread.Sleep(5000); } if (StopEvent != null) { StopEvent(); } SendMessageEvent("Работа остановлена"); }
public IEnumerable <IList <T> > GetBatch() { var stopwatch = new Stopwatch(); var batch = new List <T>(); var benchmarks = new List <RateRecord>(5); IEnumerator <T> enumerator = null; try { enumerator = _collection.GetEnumerator(); uint count = 0; stopwatch.Start(); while (enumerator.MoveNext()) { if (count == batchLength) { benchmarks.Add(new RateRecord { Length = BatchLength, ElapsedTicks = stopwatch.ElapsedTicks }); var currentBatch = batch.ToList(); batch.Clear(); if (benchmarks.Count == 10) { var currentRate = benchmarks.Average(x => x.Rate); if (currentRate > bestRate.Rate) { bestRate = new RateRecord { Length = BatchLength, ElapsedTicks = (long)benchmarks.Average(x => x.ElapsedTicks) }; batchLength = NextPowerOf2(batchLength); } // Set margin of error at 10% else if ((bestRate.Rate * .9) > currentRate) { // Shift the current length and make sure it's >= 1 var currentPowOf2 = ((batchLength >> 1) | 1); batchLength = PreviousPowerOf2(currentPowOf2); } benchmarks.Clear(); } count = 0; stopwatch.Restart(); yield return(currentBatch); } batch.Add(enumerator.Current); count++; } } finally { if (enumerator != null) { enumerator.Dispose(); } } stopwatch.Stop(); }
private void OpenOrCloseOrders(string strategyName, IStrategyDecision decision, RateRecord rec) { decimal lastValue = rec.Value; if (decision.Direction == 0) { return; } Order openedOrder = _orderController.GetOpenedOrder(strategyName, rec.Name); if (openedOrder != null) { if (openedOrder.Direction * decision.Direction > 0) { openedOrder.TakeProfit = decision.TakeProfit; } else { _orderController.CloseOrder(openedOrder, rec); } } else { _orderController.OpenOrder(strategyName, lastValue, decision.StopLoss, decision.TakeProfit, rec.Name, rec.UpdateTime, decision.AdditionalInfo); } }
/// <summary> /// 计算一个金融衍生品交易的定价和风险指标 /// </summary> /// <param name="trade">交易</param> /// <param name="market">市场数据对象</param> /// <param name="request">计算请求类型</param> /// <returns>计算结果</returns> public override IPricingResult Calculate(TTrade trade, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); if (result.IsRequested(PricingRequest.Pv)) { result.Pv = CalcPv(trade, market); } if (result.IsRequested(PricingRequest.Carry)) { result.Carry = CalcCarry(trade, market); } if (result.IsRequested(PricingRequest.Dv01)) { if (double.IsNaN(result.Pv)) { result.Pv = CalcPv(trade, market); } var mktDown = market.FixingCurve.HasValue ? market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.DiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FixingCurve.Value.Shift(1))) : market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.DiscountCurve.Value.Shift(1))); result.Dv01 = CalcPv(trade, mktDown) - result.Pv; } if (result.IsRequested(PricingRequest.Cashflow)) { result.Cashflows = trade.GetCashflows(market, false); } //Ai and AiEod are mutually exclusive requests var isEod = result.IsRequested(PricingRequest.AiEod); if (result.IsRequested(PricingRequest.Ai) || result.IsRequested(PricingRequest.AiEod)) { if (result.Cashflows == null || result.Cashflows.Length == 0) { result.Cashflows = trade.GetCashflows(market, false); } result.Ai = trade.GetAccruedInterest(market.ValuationDate, market, isEod); } if (result.IsRequested(PricingRequest.KeyRateDv01)) { if (double.IsNaN(result.Pv)) { result.Pv = CalcPv(trade, market); } var dc = new Dictionary <string, CurveRisk[]>(); var fc = new Dictionary <string, CurveRisk[]>(); Parallel.Invoke( () => CalcDiscountDv01(trade, market, result.Pv, ref dc), () => CalcResetDv01(trade, market, result.Pv, ref fc) ); result.KeyRateDv01 = PricingResultExtension.Aggregate(dc, fc); } if (result.IsRequested(PricingRequest.FairQuote)) { result.FairQuote = GetFairQuote(trade, market); } if (result.IsRequested(PricingRequest.MacDuration)) { if (result.Cashflows == null || result.Cashflows.Length == 0) { result.Cashflows = trade.GetCashflows(market, false); } var weightedCf = 0.0; var totalCf = 0.0; foreach (var cashflow in result.Cashflows) { if (cashflow.PaymentDate > market.ValuationDate) { var t = market.DiscountCurve.Value.DayCount.CalcDayCountFraction(market.ValuationDate, cashflow.PaymentDate); var df = market.DiscountCurve.Value.GetDf(market.ValuationDate, cashflow.PaymentDate); weightedCf += cashflow.PaymentAmount * df * t; totalCf += cashflow.PaymentAmount * df; } } result.MacDuration = weightedCf / totalCf; } if (result.IsRequested(PricingRequest.Pv01)) { result.Pv01 = CalcPv01(trade, market, result.Pv); } Date valueDate = result.ValuationDate; if (result.IsRequested(PricingRequest.ProductSpecific)) { var yieldCurve = market.DiscountCurve.Value; #region var psDict = new Dictionary <string, Dictionary <string, RateRecord> >(); var dayGap = new DayGap("+0BD"); var T = (trade is InterestRateSwap) ? (trade as InterestRateSwap).FloatingLeg : trade as SwapLeg; //forward rate points var tenors = new[] { "1D", "7D", "3M", "1Y" }; var fwdStartInTenors = new List <string> { "1D", "1W", "2W", "1M", "2M", "3M", "4M", "5M", "6M", "7M", "8M", "9M", "10M", "11M", "1Y" }; var totalMonths = Convert.ToInt16((yieldCurve.KeyPoints.Last().Item1 - yieldCurve.KeyPoints.First().Item1) / 30.0) + 1; for (var i = 15; i <= totalMonths; i += 3) { fwdStartInTenors.Add(i + "M"); } foreach (var tenor in tenors) { var fwdRates = new Dictionary <string, RateRecord>(); var fwdTerm = new Term(tenor); foreach (var fwdStartInTenor in fwdStartInTenors) { var fwdStartDate = dayGap.Get(T.Calendar, new Term(fwdStartInTenor).Next(valueDate)); var fwdEndDate = dayGap.Get(T.Calendar, fwdTerm.Next(fwdStartDate)); if (fwdEndDate < yieldCurve.KeyPoints.Last().Item1) { fwdRates[fwdStartInTenor] = new RateRecord() { Date = fwdStartDate.ToString(), Rate = yieldCurve.GetForwardRate(fwdStartDate, fwdTerm) }; } } psDict["forwardrates" + tenor] = fwdRates; } //spot rate var spotRates = new Dictionary <string, RateRecord>(); var spotInTenors = fwdStartInTenors; foreach (var spotInTenor in spotInTenors) { var spotDate = dayGap.Get(T.Calendar, new Term(spotInTenor).Next(valueDate)); if (spotDate <= yieldCurve.KeyPoints.Last().Item1) { spotRates[spotInTenor] = new RateRecord { Date = spotDate.ToString(), Rate = yieldCurve.ZeroRate(valueDate, spotDate, Compound.Simple) }; } } psDict["spotRates"] = spotRates; //key rates var rates = new Dictionary <string, RateRecord>(); var ccTenors = yieldCurve.GetKeyTenors().ToArray(); var mktInstruments = yieldCurve.MarketInstruments; if (mktInstruments != null) { if (mktInstruments.Length != ccTenors.Length) { throw new PricingBaseException("Number of calibration instruments mismatches number of calibrated points!"); } } for (var i = 0; i < ccTenors.Count(); ++i) { //var spotDate = mktInstruments != null ? mktInstruments[i].Instrument.GetClibrationDate() : dayGap.Get(T.Calendar, new Term(ccTenors[i]).Next(valueDate)); var spotDate = dayGap.Get(T.Calendar, new Term(ccTenors[i]).Next(valueDate)); rates[ccTenors[i]] = new RateRecord() { ContinuousRate = yieldCurve.ZeroRate(valueDate, spotDate), Date = spotDate.ToString(), DiscountFactor = yieldCurve.GetDf(valueDate, spotDate), Rate = mktInstruments == null?yieldCurve.GetSpotRate(spotDate) : mktInstruments[i].TargetValue, ProductType = mktInstruments == null ? "None" : (mktInstruments[i].Instrument is Deposit) ? "Index" : "Swap", ZeroRate = yieldCurve.ZeroRate(valueDate, spotDate, Compound.Simple), Term = ccTenors[i] }; } psDict["rates"] = rates; //discount at cash flow dates var dfs = new Dictionary <string, RateRecord>(); var dates = result.Cashflows.Select(x => x.PaymentDate); foreach (var date in dates) { dfs[date.ToString()] = new RateRecord { DiscountFactor = yieldCurve.GetDf(date) }; } psDict["discountfactor"] = dfs; //qb rate return result.ProductSpecific = psDict; #endregion } return(result); }
public virtual IStrategyDecision GetStrategyDecision(RateRecord rec) { StrategyHelper.CloseCandle(_candles, rec, CANDLES_INTERVAL_MINUTES); BaseStrategyDecision decision = new BaseStrategyDecision(); Candle maximum = GetMaximumForInterval(rec.Name, CANDLES_RANGE, _candles[rec.Name].Last()); Candle minimum = GetMinimumForInterval(rec.Name, CANDLES_RANGE, _candles[rec.Name].Last()); if (maximum == null || minimum == null) { return(decision); } if (maximum.OpenTime > minimum.OpenTime) //тренд вверх { Candle previousMaximum = GetMaximumBetween(rec.Name, minimum, maximum); if (previousMaximum != null) { Candle previousMinimum = GetMinimumBetween(rec.Name, previousMaximum, maximum); if (previousMinimum != null) { //пробойный бар Candle breakout = GetMaximumBreakout(rec.Name, previousMinimum, previousMaximum.HighPrice); if (breakout != null) { Candle previousMaximum2 = GetMaximumBetween(rec.Name, minimum, previousMaximum); if (previousMaximum2 != null) { //наш takeProfit Candle previousMinimum2 = GetMinimumBetween(rec.Name, previousMaximum2, previousMaximum); if (previousMinimum2 != null && rec.Value < breakout.LowPrice) { if (rec.Value - previousMinimum2.LowPrice > 0.0010m && breakout.HighPrice - rec.Value > 0.0005m ) { decision.TakeProfit = previousMinimum2.LowPrice; decision.StopLoss = breakout.HighPrice; StringBuilder sb = new StringBuilder(); sb.AppendFormat("Takeprofit:{0}{1}", decision.TakeProfit, Environment.NewLine); sb.AppendFormat("Stoploss:{0}{1}", decision.StopLoss, Environment.NewLine); sb.AppendFormat("Предпоследний колебательный минимум был:{0:yyy-MM-dd HH:mm}{1}", previousMinimum2.OpenTime, Environment.NewLine); sb.AppendFormat("Пробойный бар:{0:yyy-MM-dd HH:mm}{1}", breakout.OpenTime, Environment.NewLine); decision.AdditionalInfo = sb.ToString(); } } } } } } } if (minimum.OpenTime > maximum.OpenTime) // тренд вниз { Candle previousMinimum = GetMinimumBetween(rec.Name, maximum, minimum); if (previousMinimum != null) { Candle previousMaximum = GetMaximumBetween(rec.Name, previousMinimum, minimum); if (previousMaximum != null) { //пробойный бар Candle breakout = GetMinimumBreakout(rec.Name, previousMaximum, previousMinimum.LowPrice); if (breakout != null) { Candle previousMinimum2 = GetMinimumBetween(rec.Name, maximum, previousMinimum); if (previousMinimum2 != null) { //наш takeProfit Candle previousMaximum2 = GetMaximumBetween(rec.Name, previousMinimum2, previousMinimum); if (previousMaximum2 != null && rec.Value > breakout.HighPrice) { if (previousMaximum2.HighPrice - rec.Value > 0.0010m && rec.Value - breakout.LowPrice > 0.0005m ) { decision.TakeProfit = previousMaximum2.HighPrice; decision.StopLoss = breakout.LowPrice; StringBuilder sb = new StringBuilder(); sb.AppendFormat("Takeprofit:{0}{1}", decision.TakeProfit, Environment.NewLine); sb.AppendFormat("Stoploss:{0}{1}", decision.StopLoss, Environment.NewLine); sb.AppendFormat("Предпоследний колебательный максимум был:{0:yyy-MM-dd HH:mm}{1}", previousMaximum2.OpenTime, Environment.NewLine); sb.AppendFormat("Пробойный бар:{0:yyy-MM-dd HH:mm}{1}", breakout.OpenTime, Environment.NewLine); decision.AdditionalInfo = sb.ToString(); } } } } } } } return(decision); }