private void Symbol_Tick(SymbolTick obj) // MOVE unsubscribe logic to Base { if (End == default(DateTime)) // REFACTOR to base { End = DateTime.Now + TimeSpan.FromSeconds(150); } //Console.WriteLine($"[liontrender] [tick] {z} {obj} (Test time remaining: {(End-DateTime.Now).TotalSeconds.ToString("N")} seconds)"); #if !cAlgo if (End <= DateTime.Now) { Console.WriteLine("[test] Test complete. Unsubscribing from tick events."); this.Symbol.Ticked -= Symbol_Tick; } #endif }
public override void AddTick(SymbolTick si) { bool marketClosing = false; if (!AlgoUpdateTick(si, out marketClosing)) { PostProcAddTick(); return; } UpdateMinMax(); // Try Profitable SquareOff int numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); if (numOpenPositions != 0) { bool isBuy = S.TotalBuyTrades < S.TotalSellTrades; double profitPerc = GetSquareOffProfitPerc(); if (profitPerc > AlgoParams.PercMinProfit) { AlgoTryPlaceOrder(isBuy, S.CurrTick, marketClosing); } else { S.PercChangeThreshold = AlgoParams.PercSquareOffThreshold; } } else { S.PercChangeThreshold = AlgoParams.PercMarketDirectionChange; } // detect peaks and square off trigger points bool isOrderPlaceSuccess = FindPeaksAndOrder(marketClosing); PostProcAddTick(); }
void ProcessIncomingDataStream(OpenApiMessagesFactory msgFactory, byte[] rawData) { var _msg = msgFactory.GetMessage(rawData); #if TRACE_DATA_INCOMING if (isDebugIsOn) { //if (_msg.PayloadType == (int)OpenApiLib.ProtoOAPayloadType.OA_SPOT_EVENT) //{ // Console.Write("."); //} //else { Console.WriteLine("ProcessIncomingDataStream() received: " + OpenApiMessagesPresentation.ToString(_msg)); } } #endif if (!_msg.HasPayload) { return; } var lastLastHeartBeatReceived = lastHeartBeatReceived; lastHeartBeatReceived = DateTime.UtcNow; switch (_msg.PayloadType) { case (int)OpenApiLib.ProtoPayloadType.PING_RES: { var payload = msgFactory.GetPingResponse(rawData); if (payload.HasTimestamp) { ServerTime = new DateTime((long)payload.Timestamp); Console.WriteLine("[time] " + Server.Time.ToShortTimeString()); //Server.Time = DateTime.FromFileTimeUtc(); } break; } case (int)OpenApiLib.ProtoPayloadType.HEARTBEAT_EVENT: //var _payload_msg = msgFactory.GetHeartbeatEvent(rawData); var timeBetween = (lastHeartBeatReceived - lastLastHeartBeatReceived).TotalSeconds; Console.WriteLine($"<3 ({timeBetween.ToString("N1")}s)"); break; case (int)OpenApiLib.ProtoOAPayloadType.OA_EXECUTION_EVENT: { var msg = ""; var _payload_msg = msgFactory.GetExecutionEvent(rawData); if (_payload_msg.HasReasonCode) { var executionType = _payload_msg.ExecutionType.ToString().Replace("OA_ORDER_", ""); var reason = _payload_msg.HasReasonCode ? $"({_payload_msg.ReasonCode})" : ""; msg += $"*** [EXECUTION: {executionType} {reason}] *** "; } if (_payload_msg.HasOrder) { orderId = _payload_msg.Order.OrderId; var slPrice = _payload_msg.Order.HasStopLossPrice ? " sl:" + _payload_msg.Order.StopLossPrice : ""; var tpPrice = _payload_msg.Order.HasTakeProfitPrice ? " tp:" + _payload_msg.Order.TakeProfitPrice : ""; var limitPrice = _payload_msg.Order.HasLimitPrice ? " limit:" + _payload_msg.Order.LimitPrice : ""; var stopPrice = _payload_msg.Order.HasStopPrice ? " stop:" + _payload_msg.Order.StopPrice : ""; msg += $"[ORDER {orderId}] {_payload_msg.Order.TradeSide} {_payload_msg.Order.RequestedVolume} {_payload_msg.Order.SymbolName} {limitPrice}{stopPrice} {slPrice}{tpPrice}"; } else if (_payload_msg.HasPosition) { positionId = _payload_msg.Position.PositionId; var p = _payload_msg.Position; msg += $"[POSITION {positionId}] {p.TradeSide} {p.Volume} {p.SymbolName} @ {p.EntryPrice}"; } else { } Console.WriteLine(msg); } break; case (int)OpenApiLib.ProtoOAPayloadType.OA_AUTH_RES: //var payload = msgFactory.GetAuthorizationResponse(rawData); IsAuthorized = true; Console.WriteLine("[authorized]"); break; case (int)OpenApiLib.ProtoOAPayloadType.OA_SPOT_EVENT: { if (rawData.Length > 40) { Console.WriteLine("================= GOT LONG SPOT EVENT: " + rawData.Length + " ==================="); } var payload = msgFactory.GetSpotEvent(rawData); WriteUnknownFields(_msg.PayloadType, payload); //var timestamp = timestampField.VarintList[0]; //var time = new DateTime(1970, 1, 1) + TimeSpan.FromMilliseconds(timestamp); var time = new DateTime(1970, 1, 1) + TimeSpan.FromMilliseconds(payload.Timestamp); if (payload.TrendbarCount > 0 || payload.TrendbarList.Count > 0) { foreach (var bar in payload.TrendbarList) { Console.WriteLine($"*********************** TRENDBAR: {bar.Period} o:{bar.Open} h:{bar.High} l:{bar.Low} c:{bar.Close} [v:{bar.Volume}]"); if (bar.Period == ProtoOATrendbarPeriod.H1) { AccountStats.Increment(StatEventType.H1Bar); } else if (bar.Period == ProtoOATrendbarPeriod.H1) { AccountStats.Increment(StatEventType.H1Bar); } else { AccountStats.Increment(StatEventType.Other); } throw new Exception("***** got a trendbar! Celebrate!"); } } var tick = new SymbolTick { Symbol = payload.SymbolName, Ask = payload.HasAskPrice ? payload.AskPrice : double.NaN, Bid = payload.HasBidPrice ? payload.BidPrice : double.NaN, Time = time }; if (payload.HasAskPrice || payload.HasBidPrice) { AccountStats.Increment(StatEventType.Tick); #if DEBUG //if (AccountStats.Totals.Ticks % 100 == 0) //{ // Debug.WriteLine($"[stats] {AccountStats.Totals.Ticks} ticks received"); //} #endif } var symbol = (ISymbolInternal)GetSymbol(payload.SymbolName); symbol.OnTick(tick); break; } case (int)OpenApiLib.ProtoOAPayloadType.OA_SUBSCRIBE_FOR_SPOTS_RES: { var payload = msgFactory.GetSubscribeForSpotsResponse(rawData); uint?subId = payload.HasSubscriptionId ? (uint?)payload.SubscriptionId : null; #if TRACE_SUBSCRIPTIONS Console.WriteLine($"[SUBSCRIBED] {subId}"); #endif #if GET_SUBS_AFTER_SUB SendGetSpotSubscriptionReq(subId); SendGetAllSpotSubscriptionsReq(); #endif WriteUnknownFields(_msg.PayloadType, payload); break; } case (int)OpenApiLib.ProtoOAPayloadType.OA_UNSUBSCRIBE_FROM_SPOTS_RES: { var payload = msgFactory.GetUnsubscribeFromSpotsResponse(rawData); //uint? subId = payload. ? (uint?)payload.SubscriptionId : null; Debug.WriteLine($"[UNSUBSCRIBED]"); #if GET_SUBS_AFTER_SUB SendGetAllSpotSubscriptionsReq(); #endif WriteUnknownFields(_msg.PayloadType, payload); break; } case (int)OpenApiLib.ProtoOAPayloadType.OA_GET_ALL_SPOT_SUBSCRIPTIONS_RES: { #if TRACE_SUBSCRIPTIONS Debug.WriteLine($"--- GET_ALL_SPOT_SUBSCRIPTIONS_RES: ---"); var payload = msgFactory.GetGetAllSpotSubscriptionsResponse(rawData); foreach (var x in payload.SpotSubscriptionsList) { foreach (var y in x.SubscribedSymbolsList) { Debug.Write($" - subscription {x.SubscriptionId}: {y.SymbolName} periods: "); foreach (var z in y.PeriodList) { Debug.Write($" {z.ToString()}"); } Debug.WriteLine(); } } Debug.WriteLine($"--------------------------------------- "); #endif } break; case (int)OpenApiLib.ProtoOAPayloadType.OA_GET_SPOT_SUBSCRIPTION_RES: { #if TRACE_SUBSCRIPTIONS var payload = msgFactory.GetGetSpotSubscriptionResponse(rawData); Debug.WriteLine($"--- GET_SPOT_SUBSCRIPTION_RES for subscription {payload.SpotSubscription.SubscriptionId}: --- "); foreach (var y in payload.SpotSubscription.SubscribedSymbolsList) { Debug.Write($" - {y.SymbolName} periods: "); foreach (var z in y.PeriodList) { Debug.Write($"{z.ToString()} "); } Debug.WriteLine(); } Debug.WriteLine($"------------------------------------------------------ "); #endif } break; case (int)OpenApiLib.ProtoOAPayloadType.OA_SUBSCRIBE_FOR_TRADING_EVENTS_RES: { var payload = msgFactory.GetSubscribeForTradingEventsResponse(rawData); Console.WriteLine("[TRADE EVENTS] SUBSCRIBED"); } break; default: Console.WriteLine("UNHANDLED MESSAGE: " + _msg.PayloadType); break; } ; }
public static DTick GetNearestOptionTick(DTick futTick, Dictionary <int, Dictionary <int, SymbolTick> > tickStore, ref int strkPrc, DTick optTick, bool determineOwnStrkPrc = false, bool isBuy = false) { if (tickStore.Keys.Count == 0) { return(null); } if (determineOwnStrkPrc) { bool isCall = IsCallOption(tickStore.First().Value.First().Value.I.InstrumentType); strkPrc = StockUtils.GetNearestOptionStrikePrice(futTick.Di, isCall, isBuy); var tries = 0; while (!tickStore.ContainsKey(strkPrc) && tries++ < 4) { if (tickStore.Last().Key < strkPrc) { strkPrc -= 100; } else if (tickStore.First().Key > strkPrc) { strkPrc += 100; } } if (!tickStore.ContainsKey(strkPrc)) { strkPrc = tickStore.First().Key; } } DateTime datetime = futTick.Di.QuoteTime; if (!tickStore.ContainsKey(strkPrc)) { return(null); } int time = datetime.Hour * 100 + datetime.Minute; var prcStore = tickStore[strkPrc]; SymbolTick si = null; int maxTimeWindow = 15; do { if (!prcStore.ContainsKey(time)) { if (time % 100 >= 60) { time = time - 60 + 100; } time++; } else { si = prcStore[time]; } maxTimeWindow--; } while (si == null && maxTimeWindow > 0); if (si == null && optTick.Di == null) { if (prcStore.Count > 0) { si = prcStore.First().Value; } else { optTick.Di = new DerivativeSymbolQuote(1, 1, 1); } } return(si == null ? optTick : new DTick(si.D.Q, 0)); }
public override void AddTick(SymbolTick si) { if (!AlgoUpdateTick(si)) { PostProcAddTick(); return; } // Remotely called squareoff if (S.IsSquareoffAtProfit) { if (S.TotalBuyTrades != S.TotalSellTrades) { var profitPerc = GetSquareOffProfitPerc(); if (profitPerc > 0.05) { var orderPlaceCode = TryImmediateSquareOff(false, false, true); if (orderPlaceCode == OrderPlaceAlgoCode.SUCCESS || orderPlaceCode != OrderPlaceAlgoCode.RETRY) { S.IsSquareoffAtProfit = false; if (S.IsPauseAfterSquareOffAtProfit) { Pause(false); S.IsPauseAfterSquareOffAtProfit = false; } } } } } if (AlgoParams.AlgoId >= 150) { Scalper20(1, 0.5); } else if (AlgoParams.AlgoId < 20) { Scalper10(); } else if (AlgoParams.AlgoId < 30) { Scalper10(true, true); } else if (AlgoParams.AlgoId < 40) { Scalper20(1, 0.5); } else if (AlgoParams.AlgoId < 50) { Scalper20(0.5, 0.5); } else if (AlgoParams.AlgoId < 100) { Scalper20(0.5, 0.5, false, true); } else if (AlgoParams.AlgoId > 115 && AlgoParams.AlgoId < 120) { Scalper116(); } else { Scalper20(0.5, 0.4, true); } PostProcAddTick(); }
public override void AddTick(SymbolTick si) { bool marketClosing = false; if (!AlgoUpdateTick(si, out marketClosing)) { PostProcAddTick(); return; } UpdateMinMax(); // Try Profitable SquareOff int numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); if (numOpenPositions != 0) { bool isBuy = S.TotalBuyTrades < S.TotalSellTrades; double profitPerc = GetSquareOffProfitPerc(); if (profitPerc > AlgoParams.PercMinProfit) { S.IsOnceCrossedMinProfit = true; if (!isBuy && S.PercChangeFromMax > 0) { S.IsMinProfitDirectionPercRaised = true; S.PercChangeThreshold = (profitPerc - AlgoParams.PercMinProfit) / 2; } else if (isBuy && S.PercChangeFromMin < 0) { S.IsMinProfitDirectionPercRaised = true; S.PercChangeThreshold = (profitPerc - AlgoParams.PercMinProfit) / 2; } } else if (S.IsOnceCrossedMinProfit && profitPerc > 0) { if (!S.IsMinProfitDirectionPercRaised) { S.PercChangeThreshold = profitPerc / 2; } } else { S.PercChangeThreshold = AlgoParams.PercSquareOffThreshold; } } else { S.PercChangeThreshold = AlgoParams.PercMarketDirectionChange; } // detect peaks for fresh order and squareoff trigger points bool isOrderPlaceSuccess = FindPeaksAndOrder(); // reset values on order placement if (isOrderPlaceSuccess) { S.IsOnceCrossedMinProfit = false; S.IsMinProfitDirectionPercRaised = false; numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); if (numOpenPositions == 0) // this was square off trade, then reset the peak { S.LastPeakType = PeakType.NONE; } } PostProcAddTick(); }
public override void AddTick(SymbolTick si) { if (!AlgoUpdateTick(si)) { PostProcAddTick(); return; } // Get call-put tick for mock, for live implement later if (AlgoParams.IsReplayMode) { bool isBuy = S.TotalBuyTrades < S.TotalSellTrades; if (S.TotalBuyTrades != S.TotalSellTrades) { var ordCall = GetPairedSquareOffOrder(isBuy ? Position.BUY : Position.SELL, DerivativePositionType.Call, false); if (ordCall != null) { var strkPrc = (int)ordCall.OrderTick.Di.StrikePriceDouble; // get tick from tick store S.TickCall = StockUtils.GetNearestOptionTick(S.Ticks.CurrTick, S.TicksCall, ref strkPrc, S.TickCall); } else { S.TickCall = null; } var ordPut = GetPairedSquareOffOrder(isBuy ? Position.BUY : Position.SELL, DerivativePositionType.Put, false); if (ordPut != null) { var strkPrc = (int)ordPut.OrderTick.Di.StrikePriceDouble; // get tick from tick store S.TickPut = StockUtils.GetNearestOptionTick(S.Ticks.CurrTick, S.TicksPut, ref strkPrc, S.TickPut); } else { S.TickPut = null; } } } // Remotely called squareoff if (S.IsSquareoffAtProfit) { if (S.TotalBuyTrades != S.TotalSellTrades) { var profitPerc = GetSquareOffProfitPerc(); if (profitPerc > 0.05) { var orderPlaceCode = TryImmediateSquareOff(false, false, true); if (orderPlaceCode == OrderPlaceAlgoCode.SUCCESS || orderPlaceCode != OrderPlaceAlgoCode.RETRY) { S.IsSquareoffAtProfit = false; if (S.IsPauseAfterSquareOffAtProfit) { Pause(false); S.IsPauseAfterSquareOffAtProfit = false; } } } } } if (AlgoParams.AlgoId >= 150) { Scalper20(1, 0.5); } else if (AlgoParams.AlgoId < 20) { Scalper10(); } else if (AlgoParams.AlgoId < 30) { Scalper10(true, true); } else if (AlgoParams.AlgoId < 40) { Scalper20(1, 0.5); } else if (AlgoParams.AlgoId < 50) { Scalper20(0.5, 0.5); } else if (AlgoParams.AlgoId < 100) { Scalper20(0.5, 0.5, false, true); } else if (AlgoParams.AlgoId > 115 && AlgoParams.AlgoId < 120) { Scalper116(); } else { Scalper20(0.5, 0.4, true); } PostProcAddTick(); }
// Hardcoded to Bid prices // Move elsewhere, potentially reuse? private void TickToMinuteHandler(SymbolTick tick) { if (!tick.Time.IsSameMinute(ServerTimeFromTick) && tick.Time < serverTickToMinuteTime) { logger.LogWarning($"[TICK] Got old {tick.Symbol} tick for time {tick.Time} when server tick to minute time is {serverTickToMinuteTime} and server time from tick is {ServerTimeFromTick}"); } if (tick.Time > ServerTimeFromTick) { ServerTimeFromTick = tick.Time; // May trigger a bar from previous minute, for all symbols, after a delay (to wait for remaining ticks to come in) } TimedBar bar = tickToMinuteBars.TryGetValue(tick.Symbol, TimedBar.Invalid); if (bar.IsValid && !bar.OpenTime.IsSameMinute(tick.Time)) { // Immediately Trigger a finished bar even after starting the timer above. TickToMinuteBar(tick.Symbol, bar); bar = TimedBar.Invalid; } if (!bar.IsValid) { var minuteBarOpen = new DateTime(tick.Time.Year, tick.Time.Month, tick.Time.Day, tick.Time.Hour, tick.Time.Minute, 0); bar = new TimedBar(minuteBarOpen); } if (!double.IsNaN(tick.Bid)) { if (double.IsNaN(bar.Open)) { bar.Open = tick.Bid; } bar.Close = tick.Bid; if (double.IsNaN(bar.High) || bar.High < tick.Bid) { bar.High = tick.Bid; } if (double.IsNaN(bar.Low) || bar.Low > tick.Bid) { bar.Low = tick.Bid; } } if (double.IsNaN(bar.Volume)) // REVIEW - is this correct for volume? { bar.Volume = 1; } else { bar.Volume++; } if (tickToMinuteBars.ContainsKey(tick.Symbol)) { tickToMinuteBars[tick.Symbol] = bar; } else { tickToMinuteBars.Add(tick.Symbol, bar); } }
public BrokerErrorCode RunCoreAlgoLive(SymbolTick si) { return(RunCoreAlgo()); }
// Stock algo worker thread public static void BG_StockWorkerThread_SingleSymbol(object obj) { BrokerSymbolAlgosObject stockTraderObj = (BrokerSymbolAlgosObject)obj; IBroker broker = stockTraderObj.Broker; List <ITradingAlgo> algos = stockTraderObj.Algos; BrokerErrorCode errorCode = BrokerErrorCode.Success; EquitySymbolLiveTickGenerator ETicks = stockTraderObj.ETicks; DerivativeSymbolLiveTickGenerator DTicks = stockTraderObj.DTicks; bool isDayNewTicksStarted = false; bool isAnyAlgoSquareOffRetryPending = false; DateTime quoteTime; foreach (ITradingAlgo algo in algos) { algo.ErrorCode = algo.Prolog(); if (algo.ErrorCode != BrokerErrorCode.Success) { errorCode = algo.ErrorCode; } } do { errorCode = BrokerErrorCode.Success; foreach (ITradingAlgo algo in algos) { if (algo.ErrorCode != BrokerErrorCode.Success) { algo.ErrorCode = algo.Prolog(); if (algo.ErrorCode != BrokerErrorCode.Success) { errorCode = algo.ErrorCode; } } } if (!errorCode.Equals(BrokerErrorCode.Success)) { Thread.Sleep(1000 * 30); } } while (!stockTraderObj.DoStopThread && !errorCode.Equals(BrokerErrorCode.Success)); SymbolTick tick = new SymbolTick(); tick.I = stockTraderObj.Instrument; while (!stockTraderObj.DoStopThread) { if (stockTraderObj.Instrument.InstrumentType == InstrumentType.Share) { tick.E = ETicks.GetTick(false, out errorCode); } else { tick.D = DTicks.GetTick(false, out errorCode); } if (!errorCode.Equals(BrokerErrorCode.Success)) { Thread.Sleep(1000); continue; } if (stockTraderObj.Instrument.InstrumentType == InstrumentType.Share) { quoteTime = tick.E.Q[0].QuoteTime; } else { quoteTime = tick.D.Q.QuoteTime; } // to guard against previous day's ticks if (!isDayNewTicksStarted) { isDayNewTicksStarted = quoteTime.Date == DateTime.Now.Date; if (!isDayNewTicksStarted) { Thread.Sleep(10 * 1000); continue; } } // Main Algo foreach (ITradingAlgo algo in algos) { if (!algo.DoStopAlgo) { algo.IsExternallySuspended = false; algo.ErrorCode = errorCode = algo.RunCoreAlgoLive(tick); if (algo.IsOrderExecutionPending) { isAnyAlgoSquareOffRetryPending = true; } } else { algo.IsExternallySuspended = true; } } if (!isAnyAlgoSquareOffRetryPending) { Thread.Sleep(stockTraderObj.TickIntervalInMiliSeconds);//algo.GetSleepTimeInMilliSecs()); } isAnyAlgoSquareOffRetryPending = false; } foreach (ITradingAlgo algo in algos) { algo.ErrorCode = algo.Epilog(); } if (stockTraderObj.Instrument.InstrumentType == InstrumentType.Share) { ETicks.Close(); } else { DTicks.Close(); } }
public override void AddTick(SymbolTick si) { bool marketClosing = false; if (!AlgoUpdateTick(si)) { PostProcAddTick(); return; } UpdateMinMax(); OrderPlaceAlgoCode isOrderPlaceSuccess = OrderPlaceAlgoCode.ALGORISKREJECT; // ************** 1. CHECK TOP ********************** // // detect peaks and square off trigger points if (S.LastPeakType == PeakType.BOTTOM) { bool canOrderThisAnalysis = true; // whether can palce new order on same tick where squareoff is tried // Sell Squareoff check if (AlgoParams.IsSquareOffTrigger && S.PercChangeFromMax < 0 && Math.Abs(S.PercChangeFromMax) >= AlgoParams.PercSquareOffThreshold) { int numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); if (numOpenPositions != 0) { // May be add quantity also to all these calculations double profitPerc = GetSquareOffProfitPerc(); if (!AlgoParams.IsMinProfitMust || profitPerc > AlgoParams.PercMinProfit) { // SquareOff point reached canOrderThisAnalysis = AlgoTryPlaceOrder(false, S.Ticks.CurrTick) != OrderPlaceAlgoCode.SUCCESS; } } } // New sell order if (S.PercChangeFromMax < 0 && Math.Abs(S.PercChangeFromMax) >= S.PercChangeThreshold) { // Record tick abberations if (Math.Abs(S.PercChangeFromMax) - S.PercChangeThreshold > 1) { Logger.LogWarningMessage( string.Format("{3}: {0} : PriceTick non-continuous {1}: PercThreshold = {4} S.PercChangeFromMax = {2} times.", S.Ticks.CurrTick.Di.QuoteTime, _discontinuousMaxTickNum++, S.PercChangeFromMax / S.PercChangeThreshold, AlgoParams.I.Symbol, S.PercChangeThreshold)); } // New top found S.LastPeakType = PeakType.TOP; _lastPeak = S.Ticks.MaxTick; S.Ticks.MinTick = S.Ticks.CurrTick; _allPeaks.Add(S.TotalTickCount, _lastPeak); if (canOrderThisAnalysis) { isOrderPlaceSuccess = AlgoTryPlaceOrder(false, S.Ticks.CurrTick); } } } // 2. CHECK BOTTOM else if (S.LastPeakType == PeakType.TOP) { bool canOrderThisAnalysis = true; // whether can palce new order on same tick where squareoff is tried // Look for squareoff if (AlgoParams.IsSquareOffTrigger && S.PercChangeFromMin > 0 && Math.Abs(S.PercChangeFromMin) >= AlgoParams.PercSquareOffThreshold) { int numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); if (numOpenPositions != 0) { double profitPerc = GetSquareOffProfitPerc(); if (!AlgoParams.IsMinProfitMust || profitPerc > AlgoParams.PercMinProfit) { // SquareOff point reached canOrderThisAnalysis = AlgoTryPlaceOrder(true, S.Ticks.CurrTick) != OrderPlaceAlgoCode.SUCCESS; } } } // New buy trade if (S.PercChangeFromMin > 0 && Math.Abs(S.PercChangeFromMin) >= S.PercChangeThreshold) { // Record tick abberations if (Math.Abs(S.PercChangeFromMin) - S.PercChangeThreshold > 1) { Logger.LogWarningMessage( string.Format("{3}: {0} : PriceTick non-continuous {1}: PercThreshold = {4} S.PercChangeFromMin = {2} times.", S.Ticks.CurrTick.Di.QuoteTime, _discontinuousMaxTickNum++, S.PercChangeFromMax / S.PercChangeThreshold, AlgoParams.I.Symbol, S.PercChangeThreshold)); } // New bottom found S.LastPeakType = PeakType.BOTTOM; _lastPeak = S.Ticks.MinTick; S.Ticks.MaxTick = S.Ticks.CurrTick; // range of maxtick set at this point _allPeaks.Add(S.TotalTickCount, _lastPeak); if (canOrderThisAnalysis) { isOrderPlaceSuccess = AlgoTryPlaceOrder(true, S.Ticks.CurrTick); } } } // 3. 1st PEAK (TOP/BOTTOM) else if (S.LastPeakType == PeakType.NONE) { // 1st peak double percDiffMinMax = 100 * ((GetPriceForAnalysis(S.Ticks.MaxTick.Di) - GetPriceForAnalysis(S.Ticks.MinTick.Di)) / GetPriceForAnalysis(S.Ticks.MinTick.Di)); // should be > than mPercChangeThreshold bool isBuy = S.PercChangeFromMin > 0 && Math.Abs(S.PercChangeFromMin) >= S.PercChangeThreshold; bool isSell = S.PercChangeFromMax < 0 && Math.Abs(S.PercChangeFromMax) >= S.PercChangeThreshold; if (isBuy && isSell) { FileTracing.TraceOut("Error , 1st peak says both buy and sell. Bug in order placing, order not getting executed. Still recover from it.."); isBuy = Math.Abs(S.PercChangeFromMin) > Math.Abs(S.PercChangeFromMax); isSell = !isBuy; } //if (Math.Abs(percDiffMinMax) >= mPercChangeThreshold) if (isBuy || isSell) { isOrderPlaceSuccess = AlgoTryPlaceOrder(isBuy, S.Ticks.CurrTick); if (isOrderPlaceSuccess == OrderPlaceAlgoCode.SUCCESS) { // Set last peak as reverse of current tick direction S.LastPeakType = isBuy ? PeakType.BOTTOM : PeakType.TOP; if (S.LastPeakType == PeakType.BOTTOM) { // 1st peak is BOTTOM _lastPeak = S.Ticks.MinTick; } else { // 1st peak is TOP _lastPeak = S.Ticks.MaxTick; } _allPeaks.Add(S.TotalTickCount, _lastPeak); } } } PostProcAddTick(); }
// IEOD - with Only LTP files (and no re-run) algo public void RunAlgos(object obj) { int symbolCounter = 0; var sts = new List <SymbolTick>(10000); // Get algo data var brokerAccountObj = (BrokingAccountObject)obj; IBroker broker = brokerAccountObj.Broker; var algoMetadata = (AlgoMetadata)brokerAccountObj.CustomData; AddTickChartDelegate dataDelegate = algoMetadata.DataDelegate; var chartDelegate = algoMetadata.ChartDelegate; var logDelegate = algoMetadata.LogDelegate; var tickMetaData = algoMetadata.TickMetadata; string r1, r2; var isForceUpdate = algoMetadata.IsForceUpdate; var algoParams = algoMetadata.AlgoParams; var AlgoIdSet = AlgoIds; if (DoAllAlgos) { short minAlgo = 10; short maxAlgo = 160; AlgoIdSet = new short[maxAlgo - minAlgo + 1]; for (short i = minAlgo; i <= maxAlgo; i++) { AlgoIdSet[i - minAlgo] = i; } //AlgoIdSet[maxAlgo - minAlgo + 1] = 1; } // Go for each symbol foreach (var tmd in tickMetaData) { r1 = tmd.R1; r2 = tmd.R2; var symbol = tmd.Symbol; var tickFileName = tmd.Path; logDelegate(string.Format("Thread {0}: Time: {4} Starting Stock: {1} r1: {2} r2: {3}\n", Thread.CurrentThread.ManagedThreadId, symbol, r1, r2, DateTime.Now)); // CHECK TICKFILE EXISTS if (!File.Exists(tickFileName)) { Logger.LogWarningMessage(string.Format("TickFile {0} not found.", tickFileName)); continue; } // Check if ALGO results already exist (or need to be overwritten) PERIODWISE (r1, r2 combo).Checking last mktDir // If this goes past then it means need to run at least 1 mktDirPerc if (!isForceUpdate) { bool doesEOPExist = true; foreach (var algoId in AlgoIdSet) { if (GetAlgo(algoId, algoParams.Clone(), true) == null) { continue; } // if trader run is already present for this symbol, then just move to next symbol doesEOPExist = doesEOPExist && EOPTradeStats.DoesExistEOPStatsForMinMaxAlgos(symbol, algoId, MktDirectionParams[MktDirectionParams.Length - 1], r1, r2); if (!doesEOPExist) { break; } } if (doesEOPExist) { continue; } } ++symbolCounter; sts.Clear(); GC.Collect(); // Go through Each day's data for given symbol logDelegate(string.Format("Thread {0}: Stock: {1} " + "Time: {2} , Reading tickfile\n", Thread.CurrentThread.ManagedThreadId, symbol, DateTime.Now)); Dictionary <int, Dictionary <int, SymbolTick> > TicksCall = new Dictionary <int, Dictionary <int, SymbolTick> >(10); Dictionary <int, Dictionary <int, SymbolTick> > TicksPut = new Dictionary <int, Dictionary <int, SymbolTick> >(10); DateTime expiryDate = DateTime.Now; int lotSize = 50; InstrumentType instrType = InstrumentType.OptionCallIndex; Instrument instr = null; if (algoParams.IsHedgeAlgo) { Dictionary <int, Dictionary <int, SymbolTick> > dict; //OPT-CNXBAN-26-Jul-2012-10500-CE-Q25-0915 var dir = Path.GetDirectoryName(tickFileName); var allTickFiles = Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories); var allSymbolOptFiles = Directory.EnumerateFiles(dir, "OPT-" + symbol + "*", SearchOption.AllDirectories); if (allSymbolOptFiles.Count() == 0) { continue; } foreach (string filePath in allTickFiles) { var fileName = Path.GetFileNameWithoutExtension(filePath); if (!fileName.StartsWith("OPT-" + symbol)) { continue; } var fileParts = fileName.Split('-'); expiryDate = DateTime.Parse(fileParts[2] + "-" + fileParts[3] + "-" + fileParts[4]); lotSize = int.Parse(fileParts[7].Replace("Q", "")); var strkPrc = int.Parse(fileParts[5]); if (fileParts[6] == "CE") { instrType = InstrumentType.OptionCallIndex; dict = TicksCall; } else { instrType = InstrumentType.OptionPutIndex; dict = TicksPut; } instr = new Instrument(symbol, instrType, strkPrc, expiryDate, lotSize); if (!dict.ContainsKey(strkPrc)) { dict.Add(strkPrc, new Dictionary <int, SymbolTick>(400)); } var prcStore = dict[strkPrc]; var arrOpt = File.ReadAllLines(filePath); int tickCnt = 0; foreach (var s in arrOpt) { var dqi = ParseTickString(s, tmd.TickFormatType); // Add to list of DQI if (dqi == null) { continue; } dqi.InstrumentType = instrType; dqi.UnderlyingSymbol = symbol; dqi.ExpiryDateTime = expiryDate; dqi.StrikePriceDouble = strkPrc; var si = new SymbolTick(true); si.D.Q = dqi; si.I = instr; tickCnt++; var datetime = si.D.Q.QuoteTime; int time = datetime.Hour * 100 + datetime.Minute; if (!prcStore.ContainsKey(time)) { prcStore.Add(time, si); } } } } // READ TICKFILE var arr = File.ReadAllLines(tickFileName); double ltp = 0; int tickCount = 0; instrType = InstrumentType.FutureIndex; instr = new Instrument(symbol, instrType, 0, expiryDate, lotSize); foreach (var s in arr) { var dqi = ParseTickString(s, tmd.TickFormatType); // Add to list of DQI if (dqi == null) { continue; } dqi.InstrumentType = instrType; dqi.UnderlyingSymbol = symbol; dqi.ExpiryDateTime = expiryDate; // Add only stablemarket ticks, i.e. after inital 5 minutes. Start from 10 AM for stable data //if (MarketUtils.IsTimeAfter10AM(dqi.UpdateTime)) { var si = new SymbolTick(true); si.D.Q = dqi; si.I = instr; sts.Add(si); ltp += dqi.LastTradedPriceDouble; tickCount++; } } // Derive the quantity for FNO int qty = 1; double avgLotValue = 300000; if (tickCount != 0 && ltp != 0) { ltp = ltp / tickCount; qty = (int)Math.Round(avgLotValue / ltp); } foreach (var algoId in AlgoIdSet) { if (GetAlgo(algoId, algoParams.Clone(), true) == null) { continue; } // This is ALGO wise check. (for a given symbol, r1, r2) Check by last mktDirPerc if (!isForceUpdate) { // if trader run is already present for this symbol, then just move to next symbol var doesEOPExist = EOPTradeStats.DoesExistEOPStatsForMinMaxAlgos(symbol, algoId, MktDirectionParams[MktDirectionParams.Length - 1], r1, r2); if (doesEOPExist) { //Logger.LogWarningMessage( // string.Format( // "EOP TradeRun Stats for symbol={0}, algo={1} already exist. Skipping FULL symbol.", // symbol, algoId)); continue; } } foreach (var mktDirecparam in MktDirectionParams) { var percMarketDirectionChange = Math.Round(mktDirecparam, 2); // Special for 1 sec data //if (percMarketDirectionChange == 0.1)// || percMarketDirectionChange == 0.5) // if (!(symbol == "NIFTY" || symbol == "DEFTY" || symbol == "SENSEX")) // continue; // MktDirPerc wise check for a given symbol, algo, r1 and r2 if (!isForceUpdate) { // if trader run is already present for this symbol, then just move to next symbol bool doesEOPExist = EOPTradeStats.DoesExistEOPStatsForMinMaxAlgos(symbol, algoId, percMarketDirectionChange, r1, r2); if (doesEOPExist) { //Logger.LogWarningMessage( // string.Format( // "EOP TradeRun Stats for symbol={0}, algo={1}, marketDirection={2} already exist. Skipping for this combination.", // symbol, algoId, percMarketDirectionChange)); continue; } } logDelegate(string.Format("Thread {0} Time {1} ~ Stock: {2}, R1: {3}, Running {4} @ {5}%\n", Thread.CurrentThread.ManagedThreadId, DateTime.Now, symbol, r1, algoId, percMarketDirectionChange)); // RUN ALGO var algoParamsClone = algoParams.Clone(); algoParamsClone.PercMarketDirectionChange = percMarketDirectionChange; algoParamsClone.AlgoId = algoId; algoParamsClone.R1 = r1; algoParamsClone.R2 = r2; if (symbol.Contains("OPT-")) { algoParamsClone.I = new Instrument(symbol, InstrumentType.OptionCallIndex, ltp, new DateTime(2013, 03, 28), 50); } else { algoParamsClone.I = new Instrument(symbol, InstrumentType.FutureStock, 100, new DateTime(2013, 03, 28), qty); } algoParamsClone.PositionsFile = SystemUtils.GetStockRunTempFileName("Positions-" + algoParamsClone.Description()); algoParamsClone.StateFile = SystemUtils.GetStockRunTempFileName("AlgoState-" + algoParamsClone.Description()); TradingAlgo algo = GetAlgo(algoId, algoParamsClone, false); algo.Prolog(); if (algoParams.IsHedgeAlgo) { algo.S.TicksCall = TicksCall; algo.S.TicksPut = TicksPut; } //int tickCntr1Min = 0; // Run for each quote tick now out of all collected from the replay file foreach (var st in sts) { //if (!MarketUtils.IsTimeAfter10AM(dqi.UpdateTime)) //{ // continue; //} //tickCntr1Min++; try { if (algo.DoStopAlgo) { logDelegate(string.Format("Thread {0}: Stock: {1} " + "Time: {2} , Coming out due to Stop loss/NumTrades for the day\n", Thread.CurrentThread.ManagedThreadId, symbol, DateTime.Now)); break; } //if (algo.AlgoParams.AlgoId >= 120 && algo.AlgoParams.AlgoId < 150) //{ // if (tickCntr1Min % 5 == 0) // { // algo.S.TotalTickCount++; // algo.AddTick(st); // } // continue; //} algo.S.TotalTickCount++; algo.AddTick(st); } catch (Exception ex) { FileTracing.TraceOut("Exception in algo.AddTick(): " + ex.Message + "\n" + ex.StackTrace); } algo.LTP = st.GetLTP(); } algo.Epilog(); //EventResetChart(null, null); // RESET Time in Ticks //foreach (var st in sts) // st.D.Q.UpdateTime = st.D.Q.QuoteTime; } // foreach algo param } // foreach algo } //foreach symbol logDelegate(string.Format("Thread {0} completed !! at Time: {1} \n", Thread.CurrentThread.ManagedThreadId, DateTime.Now)); }