using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using TIWebApi.Clients.MarketData;
using TradeIdeas.Logging;
using TradeIdeas.MiscSupport;
using TradeIdeas.ServerConnection;
using TradeIdeas.TIProData;
using TradeIdeas.TIProData.Interfaces;
using TradeIdeas.XML;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
using static TradeIdeas.TIProGUI.CustomChannelList;
namespace TradeIdeas.TIProGUI
{
/* The GuiEnvironment class contains a lot of global variables shared by the various
* items in this library. This is typically the stuff that would be set by the main
* program and then used by most or all of the GUI.
*/
public static class GuiEnvironment
{
//Aids in manipulating data for the indices feature in the tool bar (MainForm.cs)
public struct IndicesData
{
public string Symbol;
public string Name;
public double? Change;
public double? Last;
public double? PercentChange;
public double? MaxChange;
public double? MaxPercentChange;
public bool Hidden;
public int Order;
};
public static string INDEX_FONT_FAMILY = "Microsoft Sans Serif";
///
/// Use this to find the GUI thread.
///
public static readonly Control ThreadingControl;
///
/// Call this to execute code in the GUI thread. If we are already in the GUI thread,
/// execute the code immediately and return from this function when it is done. Otherwise,
/// send the code to the GUI thread to be executed, and immediately return from this
/// function.
///
/// To execute.
public static void BeginInvokeIfRequired(MethodInvoker code)
{
if (ApplicationRunning)
ThreadingControl.BeginInvokeIfRequired(code);
//else
// Debug.Write("Ignoring call to the GUI after the GUI has shut down.");
// We do see this else case! When shutting down Control.InvokeRequired breaks down.
// We we added this.
}
static GuiEnvironment()
{ // This assertion will fail because we are called before Application.Run()
//Debug.Assert(Application.MessageLoop);
ThreadingControl = new Control();
var keepTheCompilerFromComplainingIJustNeedTheSideEffects =
ThreadingControl.Handle;
ApplicationRunning = true;
Application.ApplicationExit += delegate { ApplicationRunning = false; };
}
public static bool ApplicationRunning { get; private set; }
// For simplicity there is just one global variable set by the main program and used by
// the GUI library. This could be empty (but not null) and the GUI library would not crash
// However, without the list of translations the GUI would not have much value. It would
// show "***" in a lot of places. The nodes in this list are probably not whole xml files,
// but each one is probably a subset of the whole file available to the main program.
public static List XmlConfig = new List();
public static List AppConfig = new List();
public static bool ReceivedGlobalSettings = false;
///
/// Constant string used to indentfy a hidden form that is used by the Inno setup
/// script to determine if TI Pro is currently running.
///
public const string TIPRO_IS_RUNNING = "TradeIdeasProIsRunning";
// This includes space for the border. By setting these in advance, rather than
// waiting for the icon to come in from the server, we can do the layout immediately.
public const int ICON_WIDTH = 44;
public const int ICON_HEIGHT = 24;
public static bool RunningWin10 = false;
public static int WIDTH_INCREASE = 14;
public static int HEIGHT_INCREASE = 7;
public static int SUBSCRIBED_ODDSMAKER_TRIALS = 2147483647;
public static string DEFAULT_CONECCTION_HOST = "www.trade-ideas.com";
public static int DEFAULT_CONECCTION_PORT = 8844;
///
/// Contains the current weblink settings. Used to save to the user config settings file.
///
public static XmlNode WebLinkSettings = null;
///
/// The authorizations as populated from the server through the perms_command and perms_is_authorized in MainForm.cs.
///
public static Dictionary Authorizations = new Dictionary();
///
/// Gets executed when the robot authorization is received from the server.
///
public static Dictionary AuthorizationsCode = new Dictionary();
///
/// Contains a current list of RowData objects representing the list of AI trades. This gets
/// updated each time we receive a new AI update from the server. If the user isn't authorized
/// then this list will be empty.
///
public static List CurrentAiTrades = new List();
///
/// Contains a current list of RowData objects representing any orders in B+. Can be used for
/// plotting orders on charts.
///
public static List CurrentOrders = new List();
///
/// Contains a current list of RowData objects representing any positions in B+. Can be used for
/// plotting position data on charts.
///
public static List CurrentPositions = new List();
///
/// Contains a current list of RowData objects representing any executions in B+. Can be used for
/// plotting execution data on charts.
///
public static List CurrentExecutions = new List();
///
/// The order was moved by the user in the chart. This code will be executions after placement if not null.
///
public static Action OrderChartMoved = null;
public static Action OnDefaultTradeSizeUpdated = null;
///
/// Gets the program version identifier.
///
///
public static string GetProgramVersionId()
{
string assemblyVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
return assemblyVersion;
}
public static List ChartTradeAccounts { get; set; } = new List();
public static List DefaultHashtags { get; set; } = new List();
public static List TwitterHashtags { get; set; } = new List();
public static int AiSharesPerTrade = 1;
public static double AiDollarsPerTrade = 1000;
public static double AiRiskDollars = 100;
public static AiPositionSizing AiPositionSizingType = AiPositionSizing.FixedShares;
public enum AiPositionSizing { FixedShares, FixedDollars, BasedOnStopLoss };
public static Form MAIN_FORM_OBJECT;
public static bool CLICKED_MAIN_FORM_MENU = false; //for window positoning
public static bool CLICKED_VIEW_STRATEGY_TRADES = false; //for window positoning
public static bool CLICKED_VIEW_ALL_TRADES = false; //for window positoning
public static bool CLICKED_CHARTS = false; //for window positoning
public static bool OPTIMA = false; //for Optima customizations.
public static bool SPC = false; //for SPC sponsored build.
public static bool ETRADE = false; //for E*TRADE sponsored build.
public static bool TRADESTATION = false; //for TradeStation sponsored build.
// We retrieve the logo bitmap resource here to avoid an Argument exception when
// loading the resource in the Charts typically when you load a layout, close all windows,
// and then load the layout again, where the layout is opening 25 chart windows.
public static Bitmap LOGO_BW = TradeIdeas.TIProGUI.Properties.Resources.logo_bw;
public static Icon Icon
{ // This exists for historical reasons. Old code could be changed to use DefaultIcon
// directly.
get
{
return DefaultIcon.Icon;
}
// We could create a setter, which also uses DefaultIcon. But it's better to use
// DefaultIcon directly in that case. And that probably only happens in the main
// program.
}
public static string statusString = "";
///
/// Send a use case to the server.
/// Typically any interesting user interaction, like clicking on a button, will be recorded on the server side.
///
/// A description of the action.
/// Currently the server limits this string to 50 characters and it should really be only ASCII.
/// We need to send data to the server.
public static void RecordUseCase(string description, ISendManager sendManager)
{
if (RecordUseCaseEnabled)
sendManager.SendMessage(TalkWithServer.CreateMessage("command", "record_use_case", "description", description));
}
public static bool LimitAlertAfterHours = true;
public static bool WarnOnPrivateList = true;
public static string WarnOnPrivateListMessage = "";
public static string DefaultAlertTemplate = "";
public static string AlertWindowAlertTemplate = "";
public static string PriceAlertAlertTemplate = "";
public static string MultiStrategyWindowAlertTemplate = "";
public static string StrategyTradeWindowAlertTemplate = "";
public static string RBI_GBIWindowAlertTemplate = "";
public static string ExecutionsGridAlertTemplate = "";
public static string TwitterAPIKey = "Td78oRnSA4GavIuinBPHGVQIZ";
public static string TwitterAPISecret = "cFiBgssn8So8tfzNsRM9W5l4lUBklv0nuoCTORBKmHZ85ypDlS";
public static bool TwitterUseExternalComposer = true;
public static bool RecordUseCaseEnabled = true;
public static bool AlignSymbolPlusIconLeft = true;
public static int UserId = 0;
///
/// Records the use case for the special case of an externally linked symbol.
///
/// RowData object that was clicked on.
/// Code for source of user click. Alert = alert window, TopList = top list, MS = Multistrategy, Ticker = compare count ticker
/// Optional sendManager. If null this function will attempt to retrieve the default. If not found the use case won't be sent.
public static void RecordExternalLinkingUseCase(RowData rowData, string source, ISendManager sendManager = null)
{
RecordExternalLinkingUseCase(rowData.GetSymbol(), source, sendManager);
}
public static void RecordExternalLinkingUseCase(string symbol, string source, ISendManager sendManager = null)
{
if (null == sendManager && _connectionMasterByName.ContainsKey(""))
sendManager = _connectionMasterByName[""].SendManager;
if (null != sendManager)
GuiEnvironment.RecordUseCase(source + ".Grid.ExternalLinking." + symbol, sendManager);
}
///
/// Used for one-off troubleshooting. Must have DEBUG_LOGGING enabled in the XML file.
///
/// Message to be logged.
public static void LogMessage(string message)
{
try
{
if (GuiEnvironment.XmlConfig.Node("DEBUG_LOGGING").Property("ENABLED", "NO") == "YES")
{
string logFile = GetLogFilePath();
using (FileStream fileStream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.None))
{
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine(GetCurrentTimestamp() + "\t" + message);
}
}
}
}
catch { }
}
public static string GetCurrentTimestamp()
{
DateTime now = DateTime.Now;
return now.ToString("MM/dd/yyyy hh:mm:ss.fff tt");
}
private static string GetLogFilePath()
{
string logFile = DataDirectory + "\\debuglog." + DateTime.Now.ToString("yyyyMMdd") + ".txt";
return logFile;
}
//When saving and opening files, the state of the column visibility is retained
//via code within the DataGridViewSupport,along with the SaveLayout and RestoreLayout
//of the respective TopList,Alert,Multistrategy Forms. However when one changes the
//language on the Main Form, we're neither saving nor restoring any file. Thus, a bug occurs
//whereby any hidden columns will re-appear upon language-change.
//The below bool was created and is checked within DataGridViewSupport to ensure
//retention of any hidden columns upon language-change...
public static bool LanguageChanged = false;
//This bool is associated with the Options window.
//It is used to determine whether gridlines of alert,toplist
//and multistrategy windows will be visible or not...
public static bool ShowGridLines = true;
// This determines whether SnapToGrid is in effect or not.
public static bool SnapToGrid = true;
// This determines whether the CSVLogger tool is displayed in alert windows.
public static bool CSVLogger = false;
// This determines whether small config window is used or not.
public static bool SmallConfigWindow = true;
//This bool is associated with Options window.
//Namely allowing the user to highlight whole grid rows instead
// of indivdual cell within an alert,toplist, or multistrategy window
public static bool HighlightGridRow = true;
//The bool below is for context sensitive help within the Options window...
public static bool ShowHelp = true;
//This determines if we mute the alert sounds
public static bool MuteSounds = false;
//This determines if we sow the dev tools for the chrome browser
public static bool ShowDevTools = false;
//This is the list of recent symbol lists displayed in the send to symbol list menu
public static List RecentSymbolLists = new List();
//This is the list of excluded news sources.
public static List ExcludedNewsSources = new List();
//The below bool if for Integration Support (Options window...linking)
//single click is "true", double click is "false" . Combo box selections...
public static bool IntegrationSupportSingleClick = false;
public static bool IntegrationSupportUpDownKeys = true;
public static bool SendToExternalLinking = true;
//The following is used in Brokerage Plus.
public const int MARKET_HOURS_SECONDS = 23400;
///
/// Gets the market status string. Now holiday aware.
///
public static string GetMarketStatus()
{
DateTime marketNow = GetNowInMarketTimeZone();
DateTime marketOpen = GetMarketOpenLocalTime(marketNow);
DateTime marketClose = GetMarketCloseLocalTime();
DateTime now = ServerFormats.Now;
if (now < marketOpen)
return "Market opens " + DataCell.GetRelativeTime(marketOpen);
else if (now < marketClose)
return "Market closes " + DataCell.GetRelativeTime(marketClose);
else
return "Market closed " + DataCell.GetRelativeTime(marketClose);
}
///
/// Returns true if today is a market day else false. This is holiday and weekend aware.
///
///
public static bool IsMarketOpenToday()
{
DateTime marketNow = GetNowInMarketTimeZone();
DateTime marketOpen = GetMarketOpenLocalTime(marketNow);
if (marketNow.Date == marketOpen.Date)
return true;
else
return false;
}
///
/// Returns true if the market is open now else false. This is holiday and weekend aware.
///
///
public static bool IsMarketOpenNow()
{
DateTime marketNow = GetNowInMarketTimeZone();
DateTime marketOpen = GetMarketOpenLocalTime(marketNow);
DateTime marketClose = GetMarketCloseLocalTime();
DateTime now = ServerFormats.Now;
if (now >= marketOpen && now <= marketClose)
return true;
else
return false;
}
//The below item for the Font changes...The defaults
//are with respect to the Options Window
public static float DEFAULT_FONTSIZE = 8.25F;
public static string DEFAULT_FONT = "Microsoft Sans Serif";
public static Font FontSettings = new Font(DEFAULT_FONT, 12, FontStyle.Regular, GraphicsUnit.Point);
//The below bools pertain to the user wishing to connect his StockTwits
//account to his twitter, facebook, or LinkedIn accounts (Options Window)
public static bool stTwitter = false;
public static bool stFacebook = false;
public static bool stLinkedIn = false;
public static String MarketingLink = "https://www.trade-ideas.com/login/permission.html";
public static String BrokeragePlusMarketingLink = "https://www.trade-ideas.com/products/automate-trade-ideas-brokerage-plus/";
public static String UserMarketingData = "";
public static String MarketExploreLink = "https://www.trade-ideas.com/guide/chapter/25/25Market_Explorer.html";
public static String ChannelDescriptionsLink = "https://www.trade-ideas.com/education/channel-bar-descriptions/";
// The following strings and bool are used to support the default layout channel.
public static String DefaultLayoutCode = "";
public static String DefaultLayoutFile = "";
public static bool DefaultLayoutOn = false;
///
/// Stores chart annotations per symbol and timeframe. Persists between restarts.
///
public static ChartAnnotationCache ChartAnnotationCache = new ChartAnnotationCache();
///
/// Stores browser chart drawing tools per symbol and timeframe. Persists between restarts.
///
public static BrowserChartDrawingToolsCache BrowserChartDrawingToolsCache = new BrowserChartDrawingToolsCache();
//this bool ensures that the login webpage only displays once, and that
//is when the user sucessfully logs into his stocktwits account. This prevents
//the login screen from flashing briefly each time the user sends a message.
public static bool isStocktwitsInintialized = false;
public static bool isFacebookInintialized = false;
//odds maker results settings for the user. these are stored in ConfigSettings and user.config
public static int StartingEquity = 50000;
public static double Commission = 0.0;
public static double Slippage = 0.0;
public static int ShareSize = 100;
public static PositionSizingType PositionSizing = PositionSizingType.Shares;
// Used for Optima
public static double CommissionMinimum = 2.50;
public static double SlippageMinimum = 0.01;
// robot settings for use in makeSendToContextMenu
///
/// Code that gets executed when a context window is opening in a Trade-Ideas tool.
///
public static Action RobotStrategyMenuCode = null;
///
/// Add and clear the edit chart strategy context menu to the charts.
///
public static Action RobotStrategyEditMenu = null;
///
/// Code that gets executed when a context window is opening in a Trade-Ideas Chart for selecting the default strategy.
///
public static Action ChartStrategyMenuCode = null;
///
/// Called when the user has initiated a trade by selecting a price on the chart.
///
public static Action ChartTradeInitiated = null;
public static Action ChartManualTradeInitiated = null;
///
/// Called when the user select the open strategies link.
///
public static Action ChartOpenStrategyTab = null;
///
/// Called when the user select the open B+.
///
public static Action ChartOpenRobotInstance = null;
///
/// Called when the user select the edit default strategy link.
///
public static Action ChartEditDefaultStrategy = null;
///
/// Object containing all of the requirements to allow trading actions.
///
public static TradeRequirementsSettings TradeRequirements = new TradeRequirementsSettings();
///
/// Called when the Chart default requirements are updated.
///
public static Action ChartTradeRequirementsUpdated = null;
// default odds maker column config type
public static OddsMakerColumnConfiguration OddsMakerColumnConfigType = OddsMakerColumnConfiguration.Strategy;
public static string DataDirectory = "";
public static string AppNameInternal = "";
//favorite oddsmaker result columns
public static List OddsMakerFavoriteFilters = new List();
//common symbol lists
public static HashSet CommonSymbolListCodes = new HashSet();
public static readonly WindowIconCache DefaultIcon = new WindowIconCache();
public static CultureManager CultureManager = new CultureManager();
public static List RowDataExtensions = new List();
///
/// RowData handlers for candle data when a user right clicks on a particular candle in a chart.
///
public static List CandleDataHandlers = new List();
// recent color list
public static List RecentColors = new List();
// This is the callback for external linking. MainForm sets this up on startup so that LayoutManager can
// hook up the onSymbolClicked event handler
//public static ExternalLinkingForm externalLinkingForm;
public static ExternalLinking externalLinking;
public static Action