using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Diagnostics;
using System.Web;
using TradeIdeas.ServerConnection;
using TradeIdeas.XML;
using TradeIdeas.TIProData.Interfaces;
// OddsMakerManager is heavily based on HistoryManager.
//
// An oddsmaker both request and receive data in a similar way. But...
// - An OddsMaker request cannot be restarted.
// - We can cancel the requests. We ignored that at first in history.
// It's even more important here.
//
// Some of the fields in the message seem a little inconsistent. For example
// Success $ and % share a double value in the message as they are mutually
// exclusive. Whereas for Trailing Bars vs Trailing Percent exit conditions
// there are separate field values in the message. Same thing for things like
// exit timeouts, minutes after entry, minutes before close, at open days, and
// after close days. Right now all that is exposed through the OddsMakerRequest
// struct. You have to explicitly set a value regardless of whether it holds
// any real meaning.
//
// ProfitTarget and StopLoss work a different way still. If they are not
// present in the message, that conveys that they are unchecked. The presence
// of a value conveys that they are checked and the value sent is used. To
// set the unchecked state in the API you set these values to null.
//
// Maybe these inconsistencies should be abstracted away for the purposes of an
// API.
namespace TradeIdeas.TIProData
{
public delegate void OddsMakerProgress(string progress, OddsMaker sender);
public delegate void OddsMakerProgressXml(XmlNode progress, OddsMaker sender);
public delegate void OddsMakerStatus(OddsMaker sender);
public delegate void OddsMakerDebug(string debug, OddsMaker sender);
public delegate void OddsMakerCSVRow(string csv, OddsMaker sender);
public delegate void OddsMakerCSV(string csv, OddsMaker sender);
public delegate void OddsMakerCsvUrl(string url, OddsMaker sender);
public enum OddsMakerDisposition
{
NotStarted,
Working,
Done
}
public enum TimeoutType
{
Close,
Open,
MinutesAfterEntry,
FutureClose
}
public enum ExitConditionType
{
None,
Alert,
TrailingBars,
TrailingPercent
}
public enum SelectedLocation
{
US,
Canada
}
public enum OddsMakerColumnConfiguration
{
///
/// Use filters that are shown as columns in the strategy
///
Strategy,
///
/// Used to mean your favorite subset of columns. Now means all available columns.
///
Favorites
}
public class OddsMakerRequest
{
public string TargetFilter { get; set; }
private bool _useTargetFilter = false;
public bool UseTargetFilter
{
get { return _useTargetFilter; }
set { _useTargetFilter = value; }
}
public string StopFilter { get; set; }
private bool _useStopFilter = false;
public bool UseStopFilter
{
get { return _useStopFilter; }
set { _useStopFilter = value; }
}
public OddsMakerRequest() { }
public bool XmlMode { get; set; }
public bool SuccessDirectionUp { get; set; }
public bool SuccessTypePercent { get; set; }
public double SuccessMinMove { get; set; }
public int EntryTimeStart { get; set; }
public int EntryTimeEnd { get; set; }
public TimeoutType TimeoutType { get; set; }
public int BeforeCloseMinutes { get; set; }
public int TimeoutMinutes { get; set; }
public int AtOpenDays { get; set; }
public int AtCloseDays { get; set; }
public int DaysOfTest { get; set; }
public int SkipDays { get; set; }
public double? ProfitTarget { get; set; }
public double? StopLoss { get; set; }
public bool StopLossWiggle { get; set; }
public string EntryCondition { get; set; }
public ExitConditionType ExitConditionType { get; set; }
public double ExitConditionTrailingStop { get; set; }
public string ExitConditionAlert { get; set; }
public SelectedLocation Location { get; set; }
public bool RequestCsvFile { get; set; }
public OddsMakerColumnConfiguration ColumnConfig { get; set; }
public void Save(XmlNode description) //save to xml file (Layouts)
{
try
{
XmlNode om = description.NewNode("ODDSMAKER_REQUEST");
om.SetProperty("SUCCESS_DIRECTION_UP", SuccessDirectionUp);
om.SetProperty("SUCCESS_TYPE_PERCENT", SuccessTypePercent);
om.SetProperty("SUCCESS_MIN_MOVE", SuccessMinMove);
om.SetProperty("ENTRY_TIME_START", EntryTimeStart);
om.SetProperty("ENTRY_TIME_END", EntryTimeEnd);
om.SetProperty("TIMEOUT_TYPE", TimeoutType);
om.SetProperty("BEFORE_CLOSE_MINUTES", BeforeCloseMinutes);
om.SetProperty("TIMEOUT_MINUTES", TimeoutMinutes);
om.SetProperty("AT_OPEN_DAYS", AtOpenDays);
om.SetProperty("AT_CLOSE_DAYS", AtCloseDays);
om.SetProperty("DAYS_OF_TEST", DaysOfTest);
om.SetProperty("SKIP_DAYS", SkipDays);
if (null != ProfitTarget)
om.SetProperty("PROFIT_TARGET", ProfitTarget);
om.SetProperty("TARGET_FILTER", TargetFilter);
om.SetProperty("USE_TARGET_FILTER", UseTargetFilter);
if (null != StopLoss)
om.SetProperty("STOP_LOSS", StopLoss);
om.SetProperty("STOP_FILTER", StopFilter);
om.SetProperty("USE_STOP_FILTER", UseStopFilter);
om.SetProperty("STOP_LOSS_WIGGLE", StopLossWiggle);
om.SetProperty("ENTRY_CONDITION", EntryCondition);
om.SetProperty("EXIT_CONDITION_TYPE", ExitConditionType);
om.SetProperty("EXIT_CONDITION_TRAILING_STOP", ExitConditionTrailingStop);
om.SetProperty("EXIT_CONDITION_ALERT", ExitConditionAlert);
om.SetProperty("LOCATION", Location);
om.SetProperty("REQUEST_CSV_FILE", RequestCsvFile);
om.SetProperty("COLUMN_CONFIG", ColumnConfig);
}
catch (Exception e)
{
string debugView = e.ToString();
}
}
public void Load(XmlNode source)
{
XmlNode om = source.Node("ODDSMAKER_REQUEST");
SuccessDirectionUp = om.Property("SUCCESS_DIRECTION_UP", true);
SuccessTypePercent = om.Property("SUCCESS_TYPE_PERCENT", false);
SuccessMinMove = om.Property("SUCCESS_MIN_MOVE", 0.01);
EntryTimeStart = om.Property("ENTRY_TIME_START", 0);
EntryTimeEnd = om.Property("ENTRY_TIME_END", 30);
TimeoutType = om.PropertyEnum("TIMEOUT_TYPE", TradeIdeas.TIProData.TimeoutType.MinutesAfterEntry);
BeforeCloseMinutes = om.Property("BEFORE_CLOSE_MINUTES", 1);
TimeoutMinutes = om.Property("TIMEOUT_MINUTES", 1);
AtOpenDays = om.Property("AT_OPEN_DAYS", 1);
AtCloseDays = om.Property("AT_CLOSE_DAYS", 1);
DaysOfTest = om.Property("DAYS_OF_TEST", 1);
SkipDays = om.Property("SKIP_DAYS", 1);
ProfitTarget = om.Property("PROFIT_TARGET", 0);
TargetFilter = om.Property("TARGET_FILTER", "");
UseTargetFilter = om.Property("USE_TARGET_FILTER", false);
StopLoss = om.Property("STOP_LOSS", 0);
StopFilter = om.Property("STOP_FILTER", "");
UseStopFilter = om.Property("USE_STOP_FILTER", false);
StopLossWiggle = om.Property("STOP_LOSS_WIGGLE", false);
EntryCondition = om.Property("ENTRY_CONDITION", "");
ExitConditionType = om.PropertyEnum("EXIT_CONDITION_TYPE", TradeIdeas.TIProData.ExitConditionType.None);
ExitConditionTrailingStop = om.Property("EXIT_CONDITION_TRAILING_STOP", 1);
ExitConditionAlert = om.Property("EXIT_CONDITION_ALERT", "");
Location = om.PropertyEnum("LOCATION", SelectedLocation.US);
RequestCsvFile = om.Property("REQUEST_CSV_FILE", true);
ColumnConfig = om.PropertyEnum("COLUMN_CONFIG", OddsMakerColumnConfiguration.Strategy);
}
}
public interface OddsMaker
{
event OddsMakerProgress OddsMakerProgress;
event OddsMakerProgressXml OddsMakerProgressXml;
event OddsMakerStatus OddsMakerStatus;
event OddsMakerDebug OddsMakerDebug;
event OddsMakerCSV OddsMakerCSV;
event OddsMakerCSVRow OddsMakerCSVRow;
event OddsMakerCsvUrl OddsMakerCsvUrl;
OddsMakerDisposition OddsMakerDisposition { get; }
bool CanStart();
void Start();
// Call this to stop the request early. This will save resources on the server and
// client side.
void Stop();
}
public class OddsMakerManager
{
public static volatile bool LotsOfResults = false;
private object _mutex = new object();
private Dictionary _windows =
new Dictionary();
private class OddsMakerImpl : OddsMaker
{
private static Int64 _lastId = 0;
private readonly string _id;
private OddsMakerManager _manager;
private OddsMakerRequest _request;
private StringBuilder _csvData;
public OddsMakerImpl(OddsMakerRequest request, OddsMakerManager manager)
{
lock (typeof(OddsMakerImpl))
{
_lastId++;
_id = "OM" + _lastId.ToString();
}
_request = request;
_manager = manager;
}
public void SendRequestNow()
{ // Assume we are already in the mutex.
List