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 void ProcessTick(RateRecord rateRecord) { foreach(IStrategyProvider provider in _strategyProviders) { //analize IStrategyDecision decision = provider.GetStrategyDecision(rateRecord); //make orders OpenOrCloseOrders(provider.GetName(), decision, rateRecord); } }
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); }
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); } }
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); }
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; }
//send events private void SendNewRatesEvent(RateRecord rec, Candle candle) { if (NewRatesEvent != null) _asyncOperation.Post(delegate {NewRatesEvent(rec,candle); }, null); }
private void OnNewRatesEvent(RateRecord rec, Candle candle) { SendNewRatesEvent(rec,candle); _strategyController.ProcessTick(rec); _orderController.CloseOrdersByLimits(rec); }
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); } } }
private void SendNewRatesEvent(RateRecord rec,Candle candle) { if (NewRatesEvent != null) NewRatesEvent(rec,candle); }
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("Работа остановлена"); }
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 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; }