public static void Trace(string inMessage) { var consoleMessage = DateTime.Now.ToString() + " " + inMessage; Console.WriteLine(consoleMessage); FileTracing.TraceOut(inMessage); }
public static ProgramRemoteControl GetProgramRemoteControlValue() { string pageData = HttpHelper.GetWebPageResponse("http://sites.google.com/site/munishgoyal/", null, null, new CookieContainer()); ProgramRemoteControl controlValue = ProgramRemoteControl.RUN; if (!string.IsNullOrEmpty(pageData)) { if (pageData.Contains("StopKalaPudinaStockTraderPause")) { controlValue = ProgramRemoteControl.PAUSE; } else if (pageData.Contains("StopKalaPudinaStockTraderStop")) { controlValue = ProgramRemoteControl.STOP; } else if (pageData.Contains("StopKalaPudinaStockTraderHibernate")) { controlValue = ProgramRemoteControl.HIBERNATE; } else if (pageData.Contains("StopKalaPudinaStockTraderAtEndHibernate")) { controlValue = ProgramRemoteControl.HIBERNATEATEND; } } string traceString = string.Format("GetProgramRemoteControlValue: {0}, {1}", controlValue.ToString(), string.IsNullOrEmpty(pageData) ? "Failed Fetch" : "Succesful Contact"); FileTracing.TraceOut(traceString); return(controlValue); }
// Check Last Refresh time & if past 3 minutes then login // Even if someone else acquired login Session by weblogin etc. // Still this should work as the LastLoginRefreshTime becomes stale eventually and // resulting into relogin trigger // Keep calling this in a separate thread public BrokerErrorCode CheckAndLogInIfNeeded(bool bForceLogin, bool bCheckRemoteControl = false) { TimeSpan maxTimeWithoutRefresh = new TimeSpan(0, 3, 0); BrokerErrorCode errorCode = TouchServer(); lock (lockLoginMethod) { if (bForceLogin || (errorCode != BrokerErrorCode.Success) || ((DateTime.Now - LastLoginRefreshTime) > maxTimeWithoutRefresh)) { ProgramRemoteControl remoteControlValue = ProgramRemoteControl.RUN; if (bCheckRemoteControl) { remoteControlValue = RemoteUtils.GetProgramRemoteControlValue(); } // keep looping until PAUSE status is reset if (remoteControlValue.Equals(ProgramRemoteControl.PAUSE) || remoteControlValue.Equals(ProgramRemoteControl.STOP) || remoteControlValue.Equals(ProgramRemoteControl.HIBERNATE)) { string traceString = string.Format("CheckAndLogInIfNeeded: Remote Control {0} the LOGIN\n", remoteControlValue.ToString()); FileTracing.TraceOut(traceString); errorCode = BrokerErrorCode.RemotePausedOrStopped; } else { string traceString = string.Format("CheckAndLogInIfNeeded: Need to do actual LogIn. "); errorCode = LogIn(); traceString += "LogIn() returned: " + errorCode.ToString(); FileTracing.TraceOut(traceString); } } } return(errorCode); }
public void Login() { string postdata = "username="******"&password="******"Way2Sms login successful"); IsLoggedIn = true; } else { FileTracing.TraceInformation("Way2Sms login failed"); } // Get action value response = HttpHelper.GetWebPageResponse(URL_W2S_GETACTION, null, null, cookies); string prefix = "<input type=\"hidden\" name=\"Action\" id=\"Action\" value=\""; string postfix = "\""; string action = StringParser.GetStringBetween(response, 0, prefix, postfix, null); _action = action; var cc = cookies.GetCookies(new Uri(URL_W2S_GETACTION)); URL_W2S_ID = cc["JSESSIONID"].Value.Split('~')[1]; URL_W2S_USERCONTACTS_REFERRER += URL_W2S_ID; }
public void LogOut() { mLoggedIn = false; FileTracing.TraceOut("LogOut"); HttpHelper.GetWebPageResponse(URL_ICICI_LOGOUT, null, null, mCookieContainer); LastLoginRefreshTime = DateTime.MinValue; }
public static string GetLogContent() { FileStream logFileStream = new FileStream(FileTracing.GetTraceFilename(), FileMode.Open, FileAccess.Read, FileShare.ReadWrite); StreamReader logFileReader = new StreamReader(logFileStream); string logContent = logFileReader.ReadToEnd(); logFileReader.Close(); logFileStream.Close(); return(logContent); }
// Helper function to cancel stock specific all outstanding orders and trace it out public static BrokerErrorCode CancelStockOutstandingOrdersAndTrace(IBroker broker, string stockCode) { Dictionary <string, BrokerErrorCode> cancelOrderErrCodes; BrokerErrorCode errorCode = broker.CancelAllOutstandingEquityOrders(stockCode, out cancelOrderErrCodes); string traceString = Thread.CurrentThread.Name + ": CancelStockAllOutstandingEquityOrders: " + errorCode.ToString() + "\n"; foreach (KeyValuePair <string, BrokerErrorCode> errCodePair in cancelOrderErrCodes) { traceString += "Order: " + errCodePair.Key + ": Cancel status code is " + "\"" + errCodePair.Value.ToString() + "\"\n"; } FileTracing.TraceOut(traceString); return(errorCode); }
public BrokerErrorCode Epilog() { // While exiting the thread, cancel all the outstanding orders // Before cancel, store the state of any imbalanced outstanding order, i.e. 1-side executed(fully or partly) trade BrokerErrorCode errorCode = BrokerErrorCode.Success; string traceString = "Algo1_SimplePairedBuySellDelivery.Epilog :: ENTER"; FileTracing.TraceOut(traceString); if (algoParams.bCancelOutstandingOrdersAtEnd) { errorCode = BrokerUtils.CancelStockOutstandingOrdersAndTrace(mBroker, stockCode); } traceString = "Algo1_SimplePairedBuySellDelivery.Epilog :: EXIT"; FileTracing.TraceOut(traceString); return(errorCode); }
// Login worker thread public static void Background_LoginCheckerThread(object obj) { BrokingAccountObject brokerAccountObj = (BrokingAccountObject)obj; IBroker iciciDirectAccount = brokerAccountObj.Broker; BrokerErrorCode errorCode = BrokerErrorCode.Success; while (!brokerAccountObj.DoStopThread) { // SIMPLETODO uncomment the below line errorCode = iciciDirectAccount.CheckAndLogInIfNeeded(false); string traceString = "Periodic login check: " + errorCode.ToString(); FileTracing.TraceOut(traceString); // sleep of 3 minutes Thread.Sleep(3000 * 60); } }
public BrokerErrorCode GetOrderStatus(string orderNumber, InstrumentType instrumentType, DateTime fromDate, DateTime toDate, out OrderStatus orderStatus) { BrokerErrorCode errorCode = BrokerErrorCode.Success; orderStatus = OrderStatus.NOTFOUND; if (instrumentType == InstrumentType.Share) { Dictionary <string, EquityOrderBookRecord> orders; errorCode = GetEquityOrderBook(fromDate, toDate, false, false, null, out orders); if (errorCode.Equals(BrokerErrorCode.Success)) { foreach (KeyValuePair <string, EquityOrderBookRecord> orderPair in orders) { EquityOrderBookRecord order = orderPair.Value; if (order.OrderRefenceNumber == orderNumber) { orderStatus = order.Status; break; } } } } FileTracing.TraceOut(!errorCode.Equals(BrokerErrorCode.Success), "GetOrderStatus:" + errorCode.ToString(), TraceType.Error); return(errorCode); }
// Not used currently public static ProgramRemoteControl CheckRemoteControlInAlgo(ref bool bChecked) { // TEMPTEMP: this check is currently temporary , need to place it properly to provide pause algo functionality // Check after every 5 minutes int minutes = DateTime.Now.Minute; int seconds = DateTime.Now.Second; string traceString; ProgramRemoteControl remoteControlValue = ProgramRemoteControl.RUN; if (minutes % 5 == 1) { bChecked = false; } if ((minutes >= 5) && (minutes % 5 == 0) && !bChecked) { bChecked = true; remoteControlValue = RemoteUtils.GetProgramRemoteControlValue(); // keep looping until PAUSE status is reset while (remoteControlValue.Equals(ProgramRemoteControl.PAUSE)) { traceString = string.Format("AlgoRunner: Remote Control PAUSED the Algo, sleeping for 30 seconds before rechecking\n"); FileTracing.TraceOut(traceString); // sleep 60 seconds Thread.Sleep(60000); remoteControlValue = RemoteUtils.GetProgramRemoteControlValue(); } if (remoteControlValue.Equals(ProgramRemoteControl.STOP) || remoteControlValue.Equals(ProgramRemoteControl.HIBERNATE)) { traceString = string.Format("AlgoRunner: Remote Control issued STOP/HIBERNATE command to the Algo\n"); FileTracing.TraceOut(traceString); } } return(remoteControlValue); }
// 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)); }
// Do login public BrokerErrorCode LogIn() { if (_fatalNoTryLogin) { FileTracing.TraceOut(Thread.CurrentThread.Name + "ERROR: Not trying Actual LogIn() because now in FatalNoLoginTry mode."); return(BrokerErrorCode.FatalNoLoginTry); } BrokerErrorCode errorCode = IsLoggedIn(); if (!errorCode.Equals(BrokerErrorCode.Success)) { mLoggedIn = false; //FileTracing.TraceOut(Thread.CurrentThread.Name + ": In Actual LogIn()"); var postData = string.Format("ctl00%24Hearder1%24drpStock=India&ctl00%24Hearder1%24txtTopSearch=Stock+Name+%2F+Stock+Code&ctl00%24Hearder1%24hidHandler=https%3A%2F%2Fsecure.icicidirect.com%2FIDirectTrading%2FBasemasterpage%2FHeaderDataHandler.ashx&__EVENTTARGET=lbtLogin&__EVENTARGUMENT=&npage=&ctl00%24ContentPlaceHolder1%24hisreen=1366x768&ctl00%24ContentPlaceHolder1%24lms_lnk=&ctl00%24ContentPlaceHolder1%24txtUserId={0}&ctl00%24ContentPlaceHolder1%24txtu=&ctl00%24ContentPlaceHolder1%24m_StartIn_Fld=&ctl00%24ContentPlaceHolder1%24txtPass={1}&ctl00%24ContentPlaceHolder1%24txtDOB={2}&ctl00%24ContentPlaceHolder1%24drpTrade=12&ctl00%24Footer1%24showplus=&ctl00%24hidIsTrade=1&__VIEWSTATEGENERATOR=241519BE", mUsername, mPassword, mDOB); // re-login mCookieContainer = new CookieContainer(); // This GET is to populate session id in cookies string initGetResponse = HttpHelper.GetWebPageResponse(URL_ICICI_LOGON, null, URL_ICICI_LOGON_REFERRER, mCookieContainer); string loginResponse = HttpHelper.GetWebPageResponse(URL_ICICI_LOGON, postData, URL_ICICI_LOGON_REFERRER, mCookieContainer); if (String.IsNullOrEmpty(loginResponse)) { errorCode = BrokerErrorCode.Http; } else if ((loginResponse.IndexOf("You last accessed the site", StringComparison.OrdinalIgnoreCase) >= 0) || (IsLoggedIn() == BrokerErrorCode.Success)) { errorCode = GetImportantValues(); if (errorCode.Equals(BrokerErrorCode.Success)) { mLoggedIn = true; RefreshLastServerContactTime(); } } else { if (loginResponse.IndexOf("customer_change_password", StringComparison.OrdinalIgnoreCase) >= 0) { errorCode = BrokerErrorCode.ChangePassword; } if (loginResponse.IndexOf("echnical reason", StringComparison.OrdinalIgnoreCase) >= 0) { errorCode = BrokerErrorCode.TechnicalReason; } else if (loginResponse.IndexOf("Locked", StringComparison.OrdinalIgnoreCase) >= 0) { _fatalNoTryLogin = true; errorCode = BrokerErrorCode.Locked; } else if (loginResponse.IndexOf("Invalid Login Id or Password", StringComparison.OrdinalIgnoreCase) >= 0) { _fatalNoTryLogin = true; errorCode = BrokerErrorCode.InvalidLoginPassword; } else { errorCode = BrokerErrorCode.Unknown; } } } return(errorCode); }
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(); }
// Stock algo worker thread public static void Background_StockWorkerThread(object obj) { BrokerErrorCode errorCode = BrokerErrorCode.Success; BrokerSymbolAlgosObject stockTraderObj = (BrokerSymbolAlgosObject)obj; IBroker broker = stockTraderObj.Broker; //EquityStockTradeStats stockInfo = stockTraderObj.stockInfo; ITradingAlgo algo = stockTraderObj.Algos[0]; // Thread local params int threadRunCount = 0; int threadFailCount = 0; //string stockCode = stockInfo.StockCode; string traceString; bool bChecked = false; // On program re-run, cancel any previous outstanding orders // BUGBUGCD: is this infinite loop necessary or try only once // and come out on failure do { errorCode = algo.Prolog(); if (!errorCode.Equals(BrokerErrorCode.Success)) { Thread.Sleep(1000 * 30); } } while (!stockTraderObj.DoStopThread && !errorCode.Equals(BrokerErrorCode.Success)); while (!stockTraderObj.DoStopThread) { // Main Algo errorCode = algo.RunCoreAlgo(); // thread stats if (!errorCode.Equals(BrokerErrorCode.Success)) { threadFailCount++; } threadRunCount++; // Check remote control //ProgramRemoteControl remoteControlValue = CheckRemoteControlInAlgo(ref bChecked); //if (remoteControlValue.Equals(ProgramRemoteControl.STOP) || // remoteControlValue.Equals(ProgramRemoteControl.HIBERNATE)) // break; // Check if login problem if (errorCode == BrokerErrorCode.NotLoggedIn) { FileTracing.TraceOut("AlgoRunner: " + errorCode.ToString() + " Trying to login again\n"); // MGOYAL: TEMP SLEEP this is for external login to do some work . // External logger will have 2 minute (CheckAndLoginIfNeeded) window to complete a work before he is logged out. // Sleep for a minute // It means someone has stolen session, so let it be. if they need for more time then will set remote to PAUSE Thread.Sleep(120000); broker.LogOut(); errorCode = broker.CheckAndLogInIfNeeded(true); continue; } if (errorCode == BrokerErrorCode.InvalidLoginPassword || errorCode == BrokerErrorCode.ChangePassword) { FileTracing.TraceOut("AlgoRunner: InvalidLoginPassword, Exiting"); break; } Thread.Sleep(algo.GetSleepTimeInMilliSecs()); } errorCode = algo.Epilog(); // Trace out Thread run stats // TODO: more such fancy stuff later traceString = string.Format("AlgoRunner: Thread Run Stats: \nTotalRuns: {0}\nFailures: {1}\nFailurePercentagH: {2}", threadRunCount, threadFailCount, (double)(threadFailCount / (threadRunCount > 0 ? threadRunCount : 1)) * 100); FileTracing.TraceOut(traceString); }
public static bool GetConfig(out ProgramConfigParams config) { config = new ProgramConfigParams(); string traceString; try { config.username = ConfigurationManager.AppSettings["IciciDirect_Username"]; config.password = ConfigurationManager.AppSettings["IciciDirect_Password"]; config.bRunStockTrader = bool.Parse(ConfigurationManager.AppSettings["RunStockTrader"]); config.bRunTillMarketOpen = bool.Parse(ConfigurationManager.AppSettings["RunTillMarketOpen"]); config.runTimeInMinutes = double.Parse(ConfigurationManager.AppSettings["ProgramRunTime"]); config.bProgramRemoteControl = bool.Parse(ConfigurationManager.AppSettings["ProgramRemoteControl"]); config.numStocks = UInt32.Parse(ConfigurationManager.AppSettings["NumStocks"]); config.fundsStartingLimitAccount = double.Parse(ConfigurationManager.AppSettings["FundsStartingLimitAccount"]); config.lossLimitAccount = double.Parse(ConfigurationManager.AppSettings["LossLimitAccount"]); traceString = "\n----------- Program run configuration ----------\n"; traceString += string.Format("Run till Market Open = {0}\n", config.bRunTillMarketOpen ? bool.TrueString : bool.FalseString); traceString += string.Format("Run time of Program = {0}\n", config.runTimeInMinutes); traceString += string.Format("Remote Program Control = {0}\n", config.bProgramRemoteControl ? bool.TrueString : bool.FalseString); traceString += string.Format("Run StockTrader = {0}\n", config.bRunStockTrader); traceString += string.Format("Number of Stocks in System = {0}\n", config.numStocks); traceString += "\n----------- Account-wide Configuration ----------\n"; traceString += string.Format("Account-wide starting FundLimit = {0}\n", config.fundsStartingLimitAccount); traceString += string.Format("Account-wide loss Limit set = {0}\n", config.lossLimitAccount); traceString += "\n----------- Stock Specific Configuration ----------\n"; config.stockParams = new ProgramStockParams[config.numStocks]; for (int i = 0; i < config.numStocks; i++) { ProgramStockParams stockParams = new ProgramStockParams(); config.stockParams[i] = stockParams; string stockPrefix = "Stock" + i.ToString() + "_"; stockParams.stockCode = ConfigurationManager.AppSettings[stockPrefix + "StockCode"]; stockParams.stockTradingLot = int.Parse(ConfigurationManager.AppSettings[stockPrefix + "StockTradingLot"]); stockParams.bStartAFresh = bool.Parse(ConfigurationManager.AppSettings[stockPrefix + "StartAFresh"]); stockParams.bCancelExistingOrdersAtStart = bool.Parse(ConfigurationManager.AppSettings[stockPrefix + "CancelExistingOrdersAtStart"]); stockParams.bCancelOutstandingOrdersAtEnd = bool.Parse(ConfigurationManager.AppSettings[stockPrefix + "CancelOutstandingOrdersAtEnd"]); stockParams.stockAvailableStarting = int.Parse(ConfigurationManager.AppSettings[stockPrefix + "StockAvailableStarting"]); stockParams.initBidPrice = double.Parse(ConfigurationManager.AppSettings[stockPrefix + "InitBidPrice"]); stockParams.initOfferPrice = double.Parse(ConfigurationManager.AppSettings[stockPrefix + "InitOfferPrice"]); traceString += "---------------------------------------------------------------\n"; traceString += "Stock: #" + i.ToString() + "\n"; traceString += string.Format("Stock code = {0}\n", stockParams.stockCode); traceString += string.Format("Stock Trading lot = {0}\n", stockParams.stockTradingLot); traceString += string.Format("Start Afresh = {0}\n", stockParams.bStartAFresh); traceString += string.Format("Cancel existing outstanding orders at start= {0}\n", stockParams.bCancelExistingOrdersAtStart); traceString += string.Format("Cancel outstanding orders at exit = {0}\n", stockParams.bCancelOutstandingOrdersAtEnd); traceString += string.Format("Stock available in DP to sell at start = {0}\n", stockParams.stockAvailableStarting); traceString += string.Format("InitBidPrice = {0}\n", stockParams.initBidPrice); traceString += string.Format("InitOfferPrice = {0}\n", stockParams.initOfferPrice); traceString += "---------------------------------------------------------------\n"; } // Trace out the big config info string now at once // this contains all of APPCONFIG info FileTracing.TraceOut(traceString); } catch (Exception e) { FileTracing.TraceOut("Exception: " + e); return(false); } return(true); }
public void loggedIn(object o) { IsActive = true; FileTracing.TraceOut("Xmpp Logged in and Active."); }
} // Refresh state ends public List <EquityOrder> ReturnFilteredValidOrders(List <EquityOrder> orders) { int numOrders = orders.Count; List <EquityOrder> feasibleOrders = new List <EquityOrder>(); double orderFundLimit = OrderFundLimit; // TODO: BUGBUG make types coherent all across // some places we use uint for Quantity some places it is int int orderStockAvailable = OrderStockAvailable; // Need to weed out and return only the feasible orders as per stock's stock/fund limit for (int i = 0; i < numOrders; i++) { EquityOrder order = orders[i]; if (order.OrderDirection == OrderDirection.BUY) { // Buy trades // Order value double price = 0; double orderValue = 0; if (double.TryParse(order.LimitPrice, out price)) { orderValue = order.Quantity * price; } else { FileTracing.TraceOut("ReturnFilteredValidOrders: Could not parse order.LimitPrice"); continue; } // Estimated Brokerage double brokerage = EstimatedBrokerage(orderValue); // Funds limit needed to fund this trade double fundsNeededForTrade = orderValue + brokerage; // If order limit is able to cover the order value (incl. brokerage) then it is a feasible order, add it if (orderFundLimit >= fundsNeededForTrade) { orderFundLimit -= fundsNeededForTrade; feasibleOrders.Add(order); } } else { // Sell Trades // Order value double price = 0; double orderValue = 0; if (double.TryParse(order.LimitPrice, out price)) { orderValue = order.Quantity * price; } else { FileTracing.TraceOut("ReturnFilteredValidOrders: Could not parse order.LimitPrice"); continue; } // Estimated Brokerage double orderBrokerage = EstimatedBrokerage(orderValue); // If enough stocks are available to sell // and order limit is able to cover the brokerage costs then it is a feasible order, add it if (orderStockAvailable >= order.Quantity && orderFundLimit >= orderBrokerage) { orderFundLimit -= orderBrokerage; orderStockAvailable -= order.Quantity; feasibleOrders.Add(order); } } } return(feasibleOrders); } // ReturnFilteredValidOrders ends
// -------------- Work in Progress : TEST ------------------------// protected virtual bool FindPeaksAndOrder150() { int numOpenPositions = Math.Abs(S.TotalBuyTrades - S.TotalSellTrades); bool isFreshOrder = numOpenPositions == 0; //double percChange = OrderPlaceAlgoCode orderPlaceCode = OrderPlaceAlgoCode.ALGOLIMITREJECT; // 1. CHECK NEW TOP (Always occur for square off trade only) if (S.LastPeakType == PeakType.BOTTOM) { if (S.Ticks.PercChangeFromMax < 0 && Math.Abs(S.Ticks.PercChangeFromMax) >= S.PercChangeThreshold) { // Record tick abberations if (Math.Abs(S.Ticks.PercChangeFromMax) - S.PercChangeThreshold > 1) { Logger.LogWarningMessage( string.Format("{0}: At {1} : PriceTick non-continuous {4} times. PercThreshold = {2} S.Ticks.PercChangeFromMax = {3}.", AlgoParams.I.Symbol, S.Ticks.CurrTick.Di.QuoteTime, S.PercChangeThreshold, S.Ticks.PercChangeFromMax, S.Ticks.PercChangeFromMax / S.PercChangeThreshold)); } orderPlaceCode = AlgoTryPlaceOrder(false, S.Ticks.CurrTick); // Sell if (orderPlaceCode == OrderPlaceAlgoCode.SUCCESS) { // New TOP found S.LastPeakType = PeakType.TOP; S.Ticks.ResetMinMaxAndGetLastPeak(false, out _lastPeak); } } } // 2. CHECK NEW BOTTOM (Always occur for square off trade only) else if (S.LastPeakType == PeakType.TOP) { // Peak - New trades or pending squareoffs if (S.Ticks.PercChangeFromMin > 0 && Math.Abs(S.Ticks.PercChangeFromMin) >= S.PercChangeThreshold) { // Record tick abberations if (Math.Abs(S.Ticks.PercChangeFromMin) - S.PercChangeThreshold > 1) { Logger.LogWarningMessage( string.Format("{0}: At {1} : PriceTick non-continuous {4} times. PercThreshold = {2} S.Ticks.PercChangeFromMin = {3}.", AlgoParams.I.Symbol, S.Ticks.CurrTick.Di.QuoteTime, S.PercChangeThreshold, S.Ticks.PercChangeFromMin, S.Ticks.PercChangeFromMin / S.PercChangeThreshold)); } orderPlaceCode = AlgoTryPlaceOrder(true, S.Ticks.CurrTick); // Buy if (orderPlaceCode == OrderPlaceAlgoCode.SUCCESS) { // New BOTTTOM found S.LastPeakType = PeakType.BOTTOM; S.Ticks.ResetMinMaxAndGetLastPeak(true, out _lastPeak); } } } // 3. 1st or FRESH position PEAK (TOP/BOTTOM) (Never occurs for square off trade and always occur for fresh trade) else if (S.LastPeakType == PeakType.NONE) { bool isBuy = S.Ticks.PercChangeFromMin > 0 && Math.Abs(S.Ticks.PercChangeFromMin) >= S.PercChangeThreshold; bool isSell = S.Ticks.PercChangeFromMax < 0 && Math.Abs(S.Ticks.PercChangeFromMax) >= S.PercChangeThreshold; if (isBuy && isSell) { // May occur due to order not getting executed. But in offline analysis should not occur ideally var msg = string.Format("Error: NONE peak says both buy and sell." + "Some bug. Overcome is assume buy. max={0}, min={1}, th={2}", S.Ticks.PercChangeFromMax, S.Ticks.PercChangeFromMin, S.PercChangeThreshold); FileTracing.TraceOut(msg); isBuy = Math.Abs(S.Ticks.PercChangeFromMin) > Math.Abs(S.Ticks.PercChangeFromMax); isSell = !isBuy; } if (isBuy || isSell) { orderPlaceCode = AlgoTryPlaceOrder(isBuy, S.Ticks.CurrTick); // buy or sell if (orderPlaceCode == 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; } } } } if (orderPlaceCode == OrderPlaceAlgoCode.SUCCESS) { var tickNum = S.TotalTickCount; while (_allPeaks.ContainsKey(tickNum)) { tickNum += 1; } _allPeaks.Add(tickNum, _lastPeak); } else if (orderPlaceCode == OrderPlaceAlgoCode.RETRY) { S.IsOrderExecutionPending = true; } return(orderPlaceCode == OrderPlaceAlgoCode.SUCCESS); }
public BrokerErrorCode Prolog() { BrokerErrorCode errorCode = BrokerErrorCode.Success; string traceString = "Algo1_SimplePairedBuySellDelivery.Prolog :: ENTER"; FileTracing.TraceOut(traceString); if (algoParams.bCancelOutstandingOrdersAtStart) { errorCode = BrokerUtils.CancelStockOutstandingOrdersAndTrace(mBroker, stockCode); } if (!algoParams.bStartAFresh) { // Start from last run state and try to be in pair-execute state // There may be less than or equal to 1 lot of stock as long or short // Pick up the last trade from xml // TODO: } // Get latest quote EquitySymbolQuote[] stockPrice; errorCode = mBroker.GetEquityQuote(stockCode, out stockPrice); if (!errorCode.Equals(BrokerErrorCode.Success)) { return(errorCode); } int stockExchange = stockInfo.MainExchange == Exchange.NSE ? 0 : 1; double buyOrderValue = (stockPrice[stockExchange].LastTradePriceDouble * algoParams.StockTradingLot); buyOrderValue += stockInfo.EstimatedBrokerage(buyOrderValue); // Erroneous conditions get out, do later // TODO: right now assume stock abvailable is at least = stock trading lot // and assume limit is available //if(stockInfo.StockAvailableAtStart < // TODO: find better alternative to fit this variable if ((stockInfo.StockAvailableAtStart < algoParams.StockTradingLot) && (stockInfo.FundLimitAtStart >= 2 * buyOrderValue)) { // This means first buy the stock, then start trading it bGenerateASingleBuyOrderAtStart = true; } else if (stockInfo.StockAvailableAtStart < algoParams.StockTradingLot) { errorCode = BrokerErrorCode.InValidArg; } if (!bGenerateASingleBuyOrderAtStart && errorCode.Equals(BrokerErrorCode.Success)) { // There should be suficient stock to place a sell order to generate limit first // and then for the pair-orders // stockavailable should be at least twice the trading lot if ((stockInfo.FundLimitAtStart < buyOrderValue) && (stockInfo.StockAvailableAtStart >= 2 * algoParams.StockTradingLot)) { // Generate a sell order bGenerateASingleSellOrderAtStart = true; } else if (stockInfo.FundLimitAtStart < buyOrderValue) { errorCode = BrokerErrorCode.InValidArg; } } string price = "1"; bool bGenerateOrder = false; OrderDirection orderDirection = OrderDirection.BUY; // BUY order if (bGenerateASingleBuyOrderAtStart) { // price decision if (algoParams.initBidPrice > 0) { price = algoParams.initBidPrice.ToString(); } // First orders, only if market not open and it is first order pair else if (!MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; decimal buy = (decimal)(closePrice - ((double)(3.0 / 100) * closePrice));//prevclose - 3% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); price = buy.ToString(); } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal buy = (decimal)(ltp - ((double)(0.65 / 100) * ltp));//prevclose - 0.65% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); price = buy.ToString(); } orderDirection = OrderDirection.BUY; bGenerateASingleBuyOrderAtStart = false; bGenerateOrder = true; } // SELL order if (bGenerateASingleSellOrderAtStart) { // price decision if (algoParams.initOfferPrice > 0) { price = algoParams.initOfferPrice.ToString(); } // First orders, only if market not open and it is first order pair if (!MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; decimal sell = (decimal)(closePrice + (3.0 / 100 * closePrice));//prevclose + 3% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); price = sell.ToString(); } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal sell = (decimal)(ltp + (0.65 / 100 * ltp));//prevclose + 0.65% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); price = sell.ToString(); } orderDirection = OrderDirection.SELL; bGenerateASingleSellOrderAtStart = false; bGenerateOrder = true; } if (bGenerateOrder) { // Generate orders List <EquityOrderRecord> generatedOrders = new List <EquityOrderRecord> { new EquityOrderRecord(stockCode, algoParams.StockTradingLot, price, OrderPriceType.LIMIT, orderDirection, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0") }; List <BrokerErrorCode> errorCodes = null; // Validate orders List <EquityOrderRecord> ordersToPlace = stockInfo.ReturnFilteredValidOrders(generatedOrders); // Place validated orders errorCodes = mBroker.PlaceMultipleEquityOrders(ordersToPlace, 5); traceString = "Algo1_SimplePairedBuySellDelivery.Prolog\n" + "Stock: " + stockInfo.StockCode + " :PlaceMultipleEquityOrders: 1\n"; int o = 0; foreach (BrokerErrorCode errCodeEach in errorCodes) { EquityOrderRecord order = ordersToPlace[o++]; traceString = traceString + order.OrderDirection.ToString() + "-" + order.Quantity.ToString() + " at " + order.Price + ": " + errCodeEach.ToString() + "\n"; errorCode = errCodeEach; } FileTracing.TraceOut(traceString); } traceString = "Algo1_SimplePairedBuySellDelivery.Prolog :: EXIT"; FileTracing.TraceOut(traceString); return(errorCode); }
// Stock trading lot(qty) for orders //private int mStockTradingLot; //protected int StockTradingLot //{ // get { lock (lockObjectProperties) { return mStockTradingLot; } } // set { lock (lockObjectProperties) { mStockTradingLot = value; } } //} public BrokerErrorCode RunCoreAlgo() { #region SimpleBuySellPairSquareAlgo bool bCancelPairOrder = false; string stockCode = stockInfo.StockCode; int stockExchange = stockInfo.MainExchange == Exchange.NSE ? 0 : 1; BrokerErrorCode errorCode = BrokerErrorCode.Unknown; int tryCnt = 0; while (errorCode != BrokerErrorCode.Success && tryCnt <= 5) { // refresh stock state (doesnt have price info) errorCode = EquityStockState.EquityRefreshStockStateToday(mBroker, stockInfo); if (errorCode == BrokerErrorCode.NotLoggedIn) { mBroker.LogOut(); errorCode = mBroker.CheckAndLogInIfNeeded(true); tryCnt++; } } string traceString = "RefreshEquityStockStateToday: " + errorCode.ToString(); FileTracing.TraceOut(traceString); if (errorCode.Equals(BrokerErrorCode.Success)) { // If no buy or sell order pending, i.e. the square-off pair orders have executed // then place a pair of fresh buy-sell orders if (!(stockInfo.IsAnyOutstandingBuyOrder() || stockInfo.IsAnyOutstandingSellOrder() )) { // Place buy-sell order pair // Get latest quote EquitySymbolQuote[] stockPrice; errorCode = mBroker.GetEquityQuote(stockCode, out stockPrice); if (!errorCode.Equals(BrokerErrorCode.Success)) { return(errorCode); } // Generate orders List <EquityOrderRecord> generatedOrders = new List <EquityOrderRecord>(); string BidPrice; string OfferPrice; // price decision // First orders, only if market not open and it is first order pair if ((stockInfo.NumTrades == 0) && !MarketUtils.IsMarketOpen()) { double closePrice = stockPrice[stockExchange].PreviousClosePriceDouble; if (algoParams.initBidPrice > 0) { BidPrice = algoParams.initBidPrice.ToString(); } else { decimal buy = (decimal)(closePrice - (2.0 / 100 * closePrice));//prevclose - 3% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); BidPrice = buy.ToString(); } if (algoParams.initOfferPrice > 0) { OfferPrice = algoParams.initOfferPrice.ToString(); } else { decimal sell = (decimal)(closePrice + (2.0 / 100 * closePrice));//prevclose + 3% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); OfferPrice = sell.ToString(); } } // Subsequent orders // TODO: May put time conditions or market volatility conditions here in else if else { double ltp = stockPrice[stockExchange].LastTradePriceDouble; decimal buy = (decimal)(ltp - ((double)(0.85 / 100) * ltp));//prevclose - 0.85% buy = decimal.Subtract(buy, 0.05M); buy = decimal.Round(buy, 1); BidPrice = buy.ToString(); decimal sell = (decimal)(ltp + ((double)(0.85 / 100) * ltp));//prevclose + 0.85% sell = decimal.Add(sell, 0.05M); sell = decimal.Round(sell, 1, MidpointRounding.AwayFromZero); OfferPrice = sell.ToString(); } // Buy generatedOrders.Add(new EquityOrderRecord(stockCode, algoParams.StockTradingLot, BidPrice, OrderPriceType.LIMIT, OrderDirection.BUY, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0")); if (!bGenerateASingleBuyOrderAtStart) { // Sell generatedOrders.Add(new EquityOrderRecord(stockCode, algoParams.StockTradingLot, OfferPrice, OrderPriceType.LIMIT, OrderDirection.SELL, stockInfo.MainExchange, EquityOrderType.DELIVERY, "0", "0")); } List <BrokerErrorCode> errorCodes = null; // Validate orders List <EquityOrderRecord> ordersToPlace = stockInfo.ReturnFilteredValidOrders(generatedOrders); // Place validated orders errorCodes = mBroker.PlaceMultipleEquityOrders(ordersToPlace, 5); traceString = "Stock: " + stockInfo.StockCode + " :PlaceMultipleEquityOrders: 2\n"; int o = 0; foreach (BrokerErrorCode errCodeEach in errorCodes) { EquityOrderRecord order = ordersToPlace[o++]; traceString = traceString + order.OrderDirection.ToString() + "-" + order.Quantity.ToString() + " at " + order.Price + ": " + errCodeEach.ToString() + "\n"; // Place Order failed if (!errCodeEach.Equals(BrokerErrorCode.Success)) { // Cancel both the orders bCancelPairOrder = true; } } FileTracing.TraceOut(traceString); // Even if any one of the orders failed to place, cancel the pair if (bCancelPairOrder) { errorCode = BrokerUtils.CancelStockOutstandingOrdersAndTrace(mBroker, stockCode); } } } return(errorCode); #endregion }
public static bool GetConfigFor_StockTrader(out ProgramMKDConfig mkdConfig) { string traceString = null; mkdConfig = new ProgramMKDConfig(); try { mkdConfig.mock = bool.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_MOCK"]); traceString += string.Format("MOCK = {0}\n", mkdConfig.mock); mkdConfig.bIsReplayMode = bool.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_RunInReplayMode"]); traceString += string.Format("IsReplayMode = {0}\n", mkdConfig.bIsReplayMode); mkdConfig.replayTickFile = null; if (mkdConfig.bIsReplayMode) { mkdConfig.replayTickFile = ConfigurationManager.AppSettings["BuySellAnalyzer_ReplayTickFile"]; traceString += string.Format("ReplayTickFile = {0}\n", mkdConfig.replayTickFile); } mkdConfig.expiryDate = DateTime.ParseExact(ConfigurationManager.AppSettings["BuySellAnalyzer_Expiry"], "yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo); traceString += "ExpiryDate = " + mkdConfig.expiryDate.ToLongDateString() + "\n"; mkdConfig.stockCode = ConfigurationManager.AppSettings["BuySellAnalyzer_StockCode"]; traceString += "StockCode = " + mkdConfig.stockCode + "\n"; mkdConfig.positionsFile = "C:\\StockTraderStateFiles\\S.OpenPositions-" + mkdConfig.stockCode + ".txt"; traceString += string.Format("OpenPositionsStatusFile = {0}\n", mkdConfig.positionsFile); mkdConfig.brokerage = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_Brokerage"]); traceString += string.Format("brokerage = {0}\n", mkdConfig.brokerage); mkdConfig.instType = (InstrumentType)Enum.Parse(typeof(InstrumentType), ConfigurationManager.AppSettings["BuySellAnalyzer_Instrument"]); traceString += "InstrumentType = " + mkdConfig.instType.ToString() + "\n"; mkdConfig.quantity = ConfigurationManager.AppSettings["BuySellAnalyzer_Quantity"]; traceString += string.Format("TradeQuantity = {0}\n", mkdConfig.quantity); mkdConfig.percMarketDirectionChange = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercentageChangeForMarketDirection"]); mkdConfig.percSquareOffThreshold = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercChangeThresholdForSquareOff"]); //mkdConfig.percentageChangeForFreshBuy = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercentageChangeForFreshBuy"]); //mkdConfig.percentageChangeForShortSquareOff = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercentageChangeForShortSquareOff"]); //mkdConfig.percentageChangeForFreshShort = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercentageChangeForFreshShort"]); //mkdConfig.percentageChangeForLongSquareOff = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PercentageChangeForLongSquareOff"]); traceString += string.Format("percMarketDirectionChange = {0}\n", mkdConfig.percMarketDirectionChange); traceString += string.Format("percSquareOffThreshold = {0}\n", mkdConfig.percSquareOffThreshold); //traceString += string.Format("percentageChangeForFreshBuy = {0}\n", mkdConfig.percentageChangeForFreshBuy); //traceString += string.Format("percentageChangeForShortSquareOff = {0}\n", mkdConfig.percentageChangeForShortSquareOff); //traceString += string.Format("percentageChangeForFreshShort = {0}\n", mkdConfig.percentageChangeForFreshShort); //traceString += string.Format("percentageChangeForLongSquareOff = {0}\n", mkdConfig.percentageChangeForLongSquareOff); mkdConfig.minProfitPerc = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_MinProfitPerc"]); traceString += string.Format("minProfitPerc = {0}\n", mkdConfig.minProfitPerc); mkdConfig.stopLossPerc = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_StopLossPerc"]); traceString += string.Format("stopLossPerc = {0}\n", mkdConfig.stopLossPerc); mkdConfig.percPositionSpacing = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_PositionSpacingPerc"]); Console.WriteLine("percPositionSpacing = " + mkdConfig.percPositionSpacing); mkdConfig.maxTotalPositions = int.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_MaxTotalPositions"]); mkdConfig.maxLongPositions = int.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_MaxLongPositions"]); mkdConfig.maxShortPositions = int.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_MaxShortPositions"]); traceString += string.Format("maxTotalPositions = {0}\n", mkdConfig.maxTotalPositions); traceString += string.Format("maxLongPositions = {0}\n", mkdConfig.maxLongPositions); traceString += string.Format("maxShortPositions = {0}\n", mkdConfig.maxShortPositions); mkdConfig.longCeilingPrice = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_LongCeilingPrice"]); traceString += string.Format("longCeilingPrice = {0}\n", mkdConfig.longCeilingPrice); mkdConfig.shortFloorPrice = double.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_ShortFloorPrice"]); traceString += string.Format("shortFloorPrice = {0}\n", mkdConfig.shortFloorPrice); mkdConfig.useProbableTradeValue = bool.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_UseProbableTradeValue"]); string str_LongShort = ConfigurationManager.AppSettings["BuySellAnalyzer_LongOrShort"]; if (str_LongShort != "S" && str_LongShort != "L" && str_LongShort != "LS" && str_LongShort != "SL") { traceString += "Invalid value for str_LongShort"; FileTracing.TraceOut(traceString); return(false); } mkdConfig.allowShort = (str_LongShort == "S") || (str_LongShort == "LS") || (str_LongShort == "SL"); mkdConfig.allowLong = (str_LongShort == "L") || (str_LongShort == "LS") || (str_LongShort == "SL"); traceString += string.Format("allowShort = {0}\n", mkdConfig.allowShort); traceString += string.Format("allowLong = {0}\n", mkdConfig.allowLong); //bool bIsInitialOrder = bool.Parse(ConfigurationManager.AppSettings["BuySellAnalyzer_IsInitialOrder"]); //Order initialOrder = null; //if (bIsInitialOrder) //{ // { // string str_BuyPos = ConfigurationManager.AppSettings["BuySellAnalyzer_InitialOrder_OrderPosition"]; // double db_Price = -1; // if (double.TryParse(ConfigurationManager.AppSettings["BuySellAnalyzer_InitialOrder_OrderPrice"], out db_Price) && // (!string.IsNullOrEmpty(str_BuyPos))) // { // Position position = (Position)Enum.Parse(typeof(Position), str_BuyPos); // mkdConfig.initialOrder = new Order(position, db_Price); // } // else // { // mkdConfig.initialOrder = new Order(Position.None, 0); // } // } //} //else //{ // mkdConfig.initialOrder = new Order(Position.None, 0); //} //traceString += bIsInitialOrder ? ("InitialOrder = " + mkdConfig.ToString()) : "No Initial Order" + "\n"; FileTracing.TraceOut(traceString); } catch (Exception e) { FileTracing.TraceOut("Exception: " + e); return(false); } return(true); }
public void Trace(string message) { message = GetType().Name + " " + stockCode + " " + message; Console.WriteLine(DateTime.Now.ToString() + " " + message); FileTracing.TraceOut(message); }
// State values updated as non-incremental (i.e. each time whole of tradebook and orderbook are parsed) // Taking into account all trades, trade state variables are updated // then taking all outstanding orders, order state variables are updated // NOTH: ordering of TRADE update before ORDER update is required because trades (profit :-) ) // may have modified the FundLimitCurrent which is basically the limit available for orders public BrokerErrorCode RefreshState(Dictionary <string, EquityOrderBookRecord> orders, Dictionary <string, EquityTradeBookRecord> trades) { if (orders == null || trades == null) { return(BrokerErrorCode.InValidArg); } BrokerErrorCode errorCode = BrokerErrorCode.Success; // lock for integrity of all STATE variable set [TODO: redundant lock, may remove] lock (lockStateObject) { // None of the properties should be accessed when they are getting updated // as part of the state refresh, so hold the properties lock lock (lockObjectProperties) { // reassign the new order and trade books OutstandingOrders = orders; Trades = trades; // Reset the dynamic values ResetDynamicValues(); NumTrades = Trades.Count; // Update the Trade values foreach (KeyValuePair <string, EquityTradeBookRecord> tradePair in Trades) { EquityTradeBookRecord tradeInfo = tradePair.Value; if (tradeInfo.Direction == OrderDirection.BUY) { // Buy trades // Quantity TradeQtyBought += tradeInfo.Quantity; StockAvailableCurrent += tradeInfo.Quantity; // Trade or Estimated Brokerage double tradeBrokerage = tradeInfo.Brokerage == 0 ? EstimatedBrokerage(tradeInfo.TradeValue) : tradeInfo.Brokerage; TradeBrokerage += tradeBrokerage; // Funds limit FundLimitCurrent = FundLimitCurrent - tradeInfo.TradeValue - tradeBrokerage; string traceString = "FundLimitCurrent should never go below ZERO"; Debug.Assert(FundLimitCurrent >= 0, traceString); FileTracing.TraceOut(FundLimitCurrent < 0, traceString); } else { // Sell Trades // Quantity TradeQtySold += tradeInfo.Quantity; StockAvailableCurrent -= tradeInfo.Quantity; string traceString = "StockAvailableCurrent should never go below ZERO"; Debug.Assert(StockAvailableCurrent >= 0, traceString); FileTracing.TraceOut(StockAvailableCurrent < 0, traceString); // Trade or Estimated Brokerage double tradeBrokerage = tradeInfo.Brokerage == 0 ? EstimatedBrokerage(tradeInfo.TradeValue) : tradeInfo.Brokerage; TradeBrokerage += tradeBrokerage; // Funds limit FundLimitCurrent = FundLimitCurrent + tradeInfo.TradeValue - tradeBrokerage; traceString = "FundLimitCurrent should never go below ZERO"; Debug.Assert(FundLimitCurrent >= 0, traceString); FileTracing.TraceOut(FundLimitCurrent < 0, traceString); } // TODO: calculate brokerage properly for same day buy/sell trades } // HACKHACK: Dependency of Order limit values on Trade limit values being updated above OrderFundLimit = FundLimitCurrent; OrderStockAvailable = StockAvailableCurrent; // Also maintain the buy and sell outstanding orders separately OutstandingBuyOrders.Clear(); OutstandingSellOrders.Clear(); NumOrders = OutstandingOrders.Count; // Update the order values foreach (KeyValuePair <string, EquityOrderBookRecord> orderPair in OutstandingOrders) { EquityOrderBookRecord orderInfo = orderPair.Value; if (orderInfo.Direction == OrderDirection.BUY) { // Buy orders OutstandingBuyOrders.Add(orderPair.Key, orderInfo); // Quantity OutstandingBuyQty += orderInfo.Quantity; //because these order stocks are not really available until the buy order executes //OrderStockAvailable += orderInfo.Quantity; // Order value double orderValue = orderInfo.Quantity * orderInfo.Price; // Estimated Brokerage double orderBrokerage = EstimatedBrokerage(orderValue); OrderBrokerage += orderBrokerage; // Funds limit OrderFundLimit = OrderFundLimit - orderValue - orderBrokerage; string traceString = "OrderFundLimit should never go below ZERO"; Debug.Assert(OrderFundLimit >= 0, traceString); FileTracing.TraceOut(OrderFundLimit < 0, traceString); } else { // Sell orders OutstandingSellOrders.Add(orderPair.Key, orderInfo); // Quantity OutstandingSellQty += orderInfo.Quantity; OrderStockAvailable -= orderInfo.Quantity; string traceString = "OrderStockAvailable should never go below ZERO"; Debug.Assert(OrderStockAvailable >= 0, traceString); FileTracing.TraceOut(OrderStockAvailable < 0, traceString); // Order value double orderValue = orderInfo.Quantity * orderInfo.Price; // Estimated Brokerage double orderBrokerage = EstimatedBrokerage(orderValue); OrderBrokerage += orderBrokerage; // Funds limit will reduce because of to-be-incurred brokerage OrderFundLimit = OrderFundLimit - orderBrokerage; traceString = "OrderFundLimit should never go below ZERO"; Debug.Assert(OrderFundLimit >= 0, traceString); FileTracing.TraceOut(OrderFundLimit < 0, traceString); } } } } return(errorCode); } // Refresh state ends