context: using System;
  using System.Diagnostics;
  using System.ComponentModel;
  
  using Newtonsoft.Json;
  
  using Sq1.Core.Execution;
  using System.Collections.Generic;
  using System.Reflection;
  
  namespace Sq1.Core.DataTypes {
  	public partial class SymbolInfo {
  		[JsonIgnore]	const double PriceStepFromDde_NOT_RECEIVED = -1;
  
  
  		[Category("1. Essential"), DefaultValue(SecurityType.Stock), Description("[Stock] is linear, [Future] expires and has to be glued up (2D), [Option] has strikes (3D), [Forex] allows non-integer lots and trades Mon6am-Fri5pm EST, [CryptoCurrencies] are slow due to their JSON-over-web nature, [USBond] has 1/16 PriceStep")]
  		[JsonProperty]	public	SecurityType	SecurityType				{ get; set; }
  
  		[Category("1. Essential"), Description(""), ReadOnly(true)]
  		[JsonProperty]	public	string			Symbol						{ get; set; }
  
  		[Category("1. Essential"), Description("")]
  		[JsonProperty]	public	string			SymbolClass					{ get; set; }
  
  		[Category("1. Essential"), DefaultValue(1), Description("For {RTSIndex = MICEX * USD/RUR}: {Position.Size = Position.Size * SymbolInfo.Point2Dollar}")]
  		[JsonProperty]	public	double			Point2Dollar				{ get; set; }
  
  		[Category("1. Essential"), Description("0=DISABLED Forces killUnfilledPendings, closeOpenPositions N seconds prior to MarketInfo.GetReason_ifMarket_closedOrSuspended_secondsFromNow(int secondsFromNow) Backtest,Livesim,Live: no timer/thread, just inside StrategyExecutor for each newQuote")]
  		[JsonProperty]	public	int				GoFlat_priorTo_marketClose_clearing_sec	{ get; set; }
  
  		//[Category("EmergencyProcessor"), Description("NOT_USED Connected somehow with Point2Dollar")]
  		//[JsonProperty]	public	double			LeverageForFutures			{ get; set; }
  
  
  
  		[Browsable(false)]
  		[JsonProperty]	public	int				priceDecimals;
  
  		[Category("2. Price and Volume Units"), Description("digits after decimal dot for min Price Step; 2 for Cents, 0 for Dollars, -2 for $100"), DefaultValue(2)]
  		[JsonIgnore]	public	int				PriceDecimals				{
  			get { return this.priceDecimals; }
  			set { this.priceDecimals = value; this.raisePriceDecimalsChanged(); }
  		}
  
  		//BEFORE Pow/Log was invented: for (int i = this.Decimals; i > 0; i--) this.PriceLevelSize /= 10.0;
  		[Category("2. Price and Volume Units"), Description("TODO")]
  		[JsonIgnore]	public	double			PriceStepFromDecimal		{ get { return Math.Pow(10, -this.PriceDecimals); } }		// 10^(-2) = 0.01
  
  		[Category("2. Price and Volume Units"), Description("if not -1 then goes to PriceStep; set to -1 to use PriceStepFromDecimal for PriceStep")]
  		[JsonProperty]	public	double			PriceStepFromDde			{ get; set; }
  		
  		[Category("2. Price and Volume Units"), Description("TODO")]
  		[JsonIgnore]	public	double			PriceStep					{ get {
  			return this.PriceStepFromDde != SymbolInfo.PriceStepFromDde_NOT_RECEIVED ? this.PriceStepFromDde : this.PriceStepFromDecimal; } }
  
  		[Category("2. Price and Volume Units"), Description("Chart and Execution will display PriceDecimals+1 to visually assure Streaming and Broker adapters haven't got prices out of your expectations")]
  		[JsonIgnore]	public	string			PriceFormat					{ get { return "N" + (this.PriceDecimals); } }
  
  		[Category("2. Price and Volume Units"), DefaultValue(0), Description("digits after decimal dot for min lot Volume; valid for partial Forex lots (-5 for 0.00001) and Bitcoins (-6 for 0.0000001); for stocks/options/futures I'd set 0 here")]
  		[JsonProperty]	public	int				VolumeDecimals				{ get; set; }
  
  		//BEFORE Pow/Log was invented: for (int i = this.Decimals; i > 0; i--) this.PriceLevelSize /= 10.0;
  		[Category("2. Price and Volume Units"), Description("digits after decimal dot for min lot Volume; valid for partial Forex lots (-5 for 0.00001) and Bitcoins (-6 for 0.0000001); for stocks/options/futures I'd set 0 here")]
  		[JsonIgnore]	public	double			VolumeStepFromDecimal		{ get { return Math.Pow(10, -this.VolumeDecimals); } }		// 10^(-2) = 0.01
  
  		[Category("2. Price and Volume Units"), Description("Chart and Execution will display VolumeDecimals+1 to visually assure Streaming and Broker adapters haven't got volumes out of your expectations")]
  		[JsonIgnore]	public	string			VolumeFormat				{ get { return "N" + (this.VolumeDecimals); } }
  
  
  
  		[Category("3. Pre-OrderProcessor"), Description("prior to Emitting, auto-convert Market orders by setting a Broker-acceptable Price: [MarketZeroSentToBroker] will set Alert[Market].Price=0 and send it;[MarketMinMaxSentToBroker] sets Alert.Price to Streaming's two special values received per instrument (see QUIK to Excel import); [LimitCrossMarket] puts counterparty's current observed price from the other side of the spread; [LimitTidal] is good for frequent fluctuations, saves you spread but has less chance to get fill; auto-conversion is useful for: 1) Forex doesn't support market orders (MT4/MT5?); 2) Market Buy for RTS-Index must mention MaxPrice instead of 0/omitted"), DefaultValue(MarketOrderAs.MarketZeroSentToBroker)]
  		[JsonProperty]	public	MarketOrderAs	MarketOrderAs				{ get; set; }
  
  		[Browsable(false)]
  		[JsonIgnore]	public	bool			MarketZeroOrMinMax			{ get {
  				return this.MarketOrderAs == MarketOrderAs.MarketZeroSentToBroker
  					|| this.MarketOrderAs == MarketOrderAs.MarketMinMaxSentToBroker;
  			} }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue("10,20,30,40"), Description("")]
  		[JsonProperty]	public	string			SlippagesCrossMarketCsv				{ get; set; }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue("10,20,30,40"), Description("")]
  		[JsonProperty]	public	string			SlippagesTidalCsv				{ get; set; }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			UseFirstSlippageForMarketAlertsAsLimit	{ get; set; }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue(true), Description("For StopSell + ")]
  		[JsonProperty]	public	bool			NOT_USED_ReplaceTidalWithCrossMarket	{ get; set; }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue(100), Description("")]
  		[JsonProperty]	public	int				NOT_USED_ReplaceTidalMillis			{ get; set; }
  
  		[Category("3. Pre-OrderProcessor"), DefaultValue(false), Description("")]
  		[JsonProperty]	public	bool			NOT_USED_MarketOrders_priceFill_bringBackFromOutrageous			{ get; set; }
  
  
  
  		[Category("4. OrderProcessor"), DefaultValue(true),		Description("for same-bar open+close (MA crossover), SameBarPolarCloseThenOpen=[True] will submit close first, wait for Close=>Filled/KilledPending + SequencedOpeningAfterClosedDelayMillis")]
  		[JsonProperty]	public	bool			SameBarPolarCloseThenOpen	{ get; set; }
  
  		[Category("4. OrderProcessor"), DefaultValue(100),		Description("for same-bar open+close (MA crossover), SameBarPolarCloseThenOpen=[True] will submit close first, wait for Close=>Filled/KilledPending + SequencedOpeningAfterClosedDelayMillis")]
  		[JsonProperty]	public	int				SequencedOpeningAfterClosedDelayMillis		{ get; set; }
  
  		[Category("4. OrderProcessor"), DefaultValue(false),	Description("For each Broker.OrderSubmit(), check if a similar [TBD] order is already in the Pendings; useful when you are debugging your strategy that shoots the same order multiple times by mistake")]
  		[JsonProperty]	public	bool			CheckForSimilarAlreadyPending { get; set; }
  
  
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(false),	Description("")]
  		[JsonProperty]	public	bool			IfNoTransactionCallback_TimerEnabled					{ get; set; }
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(400),	Description("")]
  		[JsonProperty]	public	int				IfNoTransactionCallback_MillisAllowed					{ get; set; }
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(true),	Description("QUIK: NEVER_RECONNECT it won't call you asyncs for current pending orders")]
  		[JsonProperty]	public	bool			IfNoTransactionCallback_ReconnectBrokerDll				{ get; set; }
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(true),	Description("")]
  		[JsonProperty]	public	bool			IfNoTransactionCallback_Kill_StuckInSubmitted			{ get; set; }
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(true),	Description("")]
  		[JsonProperty]	public	bool			IfNoTransactionCallback_Resubmit						{ get; set; }
  
  		[Category("5.1 OrderPostProcessor StuckInSubmitted: Reconnect, Kill, Resubmit"), DefaultValue(3),		Description("")]
  		[JsonProperty]	public	int				IfNoTransactionCallback_ResubmitLimit					{ get; set; }
  
  
  
  		[Category("5.2 OrderPostProcessor:Replace Limit Orders after Expiration @WaitingBrokerFill"), DefaultValue(15000),		Description("if!=-1: 1) Kill Pending Limit + wait it's killed, 2) use SlippagesCrossMarketCsv for CrossMarket and SlippagesTidalCsv for Tidal, 3) send replacement order with more cutting-through slippage")]
  		[JsonProperty]	public	int				LimitExpiresAfterMillis		{ get; set; }
  
  		[Category("5.2 OrderPostProcessor:Replace Limit Orders after Expiration @WaitingBrokerFill"), DefaultValue(true), Description("Kill->Wait->SubmitReplacement using {SlippagesCrossMarketCsv/SlippagesTidalCsv} after ReSubmitLimitNotFilledWithinMillis")]
  		[JsonProperty]	public	bool			LimitExpiredResubmit		{ get; set; }
  
  		[Category("5.2 OrderPostProcessor:Replace Limit Orders after Expiration @WaitingBrokerFill"), DefaultValue(true), Description("if the price went out of grasp and your strategy will issue a new identical alert OnNextStaticBar")]
  		[JsonProperty]	public	bool			LimitExpired_KillUnfilledWithLastSlippage		{ get; set; }
  
  
  
  		[Category("5.3 OrderPostProcessor:ReplaceRejected"), DefaultValue(true), Description("OrderPostProcessorRejected is somehow different than OrderPostProcessorEmergency... sorry")]
  		[JsonProperty]	public	bool			RejectedResubmit					{ get; set; }
  
  		[Category("5.3 OrderPostProcessor:ReplaceRejected"), DefaultValue(true), Description("OrderPostProcessorRejected is somehow different than OrderPostProcessorEmergency... sorry")]
  		[JsonProperty]	public	bool			RejectedKill						{ get; set; }
  
  		[Category("5.3 OrderPostProcessor:ReplaceRejected"), DefaultValue(false), Description("OrderPostProcessorEmergency and OrderPostProcessorEmergency will increase the distance (=> decrease the profit) by using next available from SlippagesBuy/SlippagesSell")]
  		[JsonProperty]	public	bool			RejectedResubmitWithNextSlippage	{ get; set; }
  
  
  		[Category("5.9 OrderPostProcessor:Emergency"), DefaultValue(5), Description("EmergencyClose is PostProcessor's thread that kicks in when triggers when Position's Close was Rejected (Ctrl+Shift+F: InStateErrorComplementaryEmergencyState)")]
  		[JsonProperty]	public	int				EmergencyCloseAttemptsMax				{ get; set; }
  
  		[Category("5.9 OrderPostProcessor:Emergency"), DefaultValue(100), Description("EmergencyClose will sleep EmergencyCloseInterAttemptDelayMillis in its thread and repeat Closing of a Rejected ExitOrder, until ExitOrder.Clone will be returned by the BrokerAdapter as Filled, EmergencyCloseAttemptsMax times max")]
  		[JsonProperty]	public	int				EmergencyCloseInterAttemptDelayMillis	{ get; set; }
  
  
  		[Category("6. Other"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			SimBugOutOfBarStopsFill		{ get; set; }
  
  		[Category("6. Other"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			SimBugOutOfBarLimitsFill	{ get; set; }
  
  
  
  		[Category("7. DdeMonitor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			Level2AskShowHoles			{ get; set; }
  
  		[Category("7. DdeMonitor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			Level2ShowSpread			{ get; set; }
  
  		[Category("7. DdeMonitor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public	bool			Level2BidShowHoles			{ get; set; }
  
  		[Category("7. DdeMonitor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public bool				Level2ShowCumulativesInsteadOfLots	{ get; set; }
  
  		[Category("7. DdeMonitor"), DefaultValue(true), Description("")]
  		[JsonProperty]	public int				Level2PriceLevels			{ get; set; }
  
  
  		public SymbolInfo() { 		// used by JSONdeserialize() /  XMLdeserialize()
  			this.SecurityType					= SecurityType.Stock;
  			this.Symbol							= "UNKNOWN_SYMBOL";
  			this.SymbolClass					= "";
  			this.Point2Dollar					= 1.0;
  			this.GoFlat_priorTo_marketClose_clearing_sec = 0;
  
  			this.PriceDecimals					= 2;
  			this.PriceStepFromDde				= SymbolInfo.PriceStepFromDde_NOT_RECEIVED;
  			this.VolumeDecimals					= 0;	// if your Forex Symbol uses lotMin=0.001, DecimalsVolume = 3 
  			this.SameBarPolarCloseThenOpen		= true;
  			this.SequencedOpeningAfterClosedDelayMillis = 1000;
  			this.MarketOrderAs							= MarketOrderAs.Unknown;
  			this.NOT_USED_ReplaceTidalWithCrossMarket	= false;
  			this.NOT_USED_ReplaceTidalMillis			= 0;
  			this.SlippagesCrossMarketCsv		= "";
  			this.SlippagesTidalCsv				= "";
  
  			this.IfNoTransactionCallback_TimerEnabled			= false;
  			this.IfNoTransactionCallback_MillisAllowed			= 400;
  			this.IfNoTransactionCallback_ReconnectBrokerDll		= false;
  			this.IfNoTransactionCallback_Kill_StuckInSubmitted	= true;
  			this.IfNoTransactionCallback_Resubmit				= true;
  			this.IfNoTransactionCallback_ResubmitLimit			= 3;
  		
  			this.RejectedKill							= true;
  			this.RejectedResubmit						= true;
  			this.RejectedResubmitWithNextSlippage		= false;
  
  			this.UseFirstSlippageForMarketAlertsAsLimit	= false;
  			this.EmergencyCloseInterAttemptDelayMillis	= 8000;
  
  			this.LimitExpiresAfterMillis		= 15000;
  			this.LimitExpiredResubmit			= false;
  			this.LimitExpired_KillUnfilledWithLastSlippage = true;
  
  			this.EmergencyCloseAttemptsMax		= 5;
  
  			this.Level2AskShowHoles				= true;
  			this.Level2ShowSpread				= true;
  			this.Level2BidShowHoles				= true;
  			this.Level2PriceLevels				= 10;
  		}
  
  		string getSlippagesCsv(MarketOrderAs crossOrTidal) {
  			string ret = null;
  
gt: 			switch (crossOrTidal) {