34 using System.Collections.Concurrent;
35 using System.Collections.Generic;
49 private readonly PyObject _algorithm;
50 private readonly dynamic _onData;
51 private readonly dynamic _onMarginCall;
56 private dynamic _onBrokerageDisconnect;
57 private dynamic _onBrokerageMessage;
58 private dynamic _onBrokerageReconnect;
59 private dynamic _onSplits;
60 private dynamic _onDividends;
61 private dynamic _onDelistings;
62 private dynamic _onSymbolChangedEvents;
63 private dynamic _onEndOfDay;
64 private dynamic _onMarginCallWarning;
65 private dynamic _onOrderEvent;
66 private dynamic _onCommand;
67 private dynamic _onAssignmentOrderEvent;
68 private dynamic _onSecuritiesChanged;
69 private dynamic _onFrameworkSecuritiesChanged;
93 Logging.Log.Trace($
"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");
95 var module = Py.Import(moduleName);
97 Logging.Log.Trace($
"AlgorithmPythonWrapper(): {moduleName} successfully imported.");
99 var pyList = module.Dir();
100 foreach (var name
in pyList)
103 var attr = module.GetAttr(name.ToString());
104 var repr = attr.Repr().GetStringBetweenChars(
'\'',
'\'');
106 if (repr.StartsWith(moduleName) &&
107 attr.TryConvert(out type,
true) &&
110 Logging.Log.Trace(
"AlgorithmPythonWrapper(): Creating IAlgorithm instance.");
112 _algorithm = attr.Invoke();
114 var dynAlgorithm = _algorithm as dynamic;
117 dynAlgorithm.SetPandasConverter();
120 _baseAlgorithm = dynAlgorithm.AsManagedObject(type);
124 _onData = _algorithm.GetPythonMethod(
"OnData");
126 _onMarginCall = _algorithm.GetPythonMethod(
"OnMarginCall");
128 PyObject endOfDayMethod = _algorithm.GetPythonMethod(
"OnEndOfDay");
129 if (endOfDayMethod !=
null)
133 var argCount = endOfDayMethod.GetPythonArgCount();
150 _onBrokerageDisconnect = _algorithm.GetMethod(
"OnBrokerageDisconnect");
151 _onBrokerageMessage = _algorithm.GetMethod(
"OnBrokerageMessage");
152 _onBrokerageReconnect = _algorithm.GetMethod(
"OnBrokerageReconnect");
153 _onSplits = _algorithm.GetMethod(
"OnSplits");
154 _onDividends = _algorithm.GetMethod(
"OnDividends");
155 _onDelistings = _algorithm.GetMethod(
"OnDelistings");
156 _onSymbolChangedEvents = _algorithm.GetMethod(
"OnSymbolChangedEvents");
157 _onEndOfDay = _algorithm.GetMethod(
"OnEndOfDay");
158 _onCommand = _algorithm.GetMethod(
"OnCommand");
159 _onMarginCallWarning = _algorithm.GetMethod(
"OnMarginCallWarning");
160 _onOrderEvent = _algorithm.GetMethod(
"OnOrderEvent");
161 _onAssignmentOrderEvent = _algorithm.GetMethod(
"OnAssignmentOrderEvent");
162 _onSecuritiesChanged = _algorithm.GetMethod(
"OnSecuritiesChanged");
163 _onFrameworkSecuritiesChanged = _algorithm.GetMethod(
"OnFrameworkSecuritiesChanged");
170 if (_algorithm ==
null)
172 throw new Exception(
"Please ensure that one class inherits from QCAlgorithm.");
180 e = interpreter.
Interpret(e, interpreter);
182 throw new Exception($
"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
205 return _baseAlgorithm.BrokerageMessageHandler;
232 public ConcurrentQueue<string>
DebugMessages => _baseAlgorithm.DebugMessages;
237 public DateTime
EndDate => _baseAlgorithm.EndDate;
242 public ConcurrentQueue<string>
ErrorMessages => _baseAlgorithm.ErrorMessages;
251 return _baseAlgorithm.HistoryProvider;
283 public ConcurrentQueue<string>
LogMessages => _baseAlgorithm.LogMessages;
293 return _baseAlgorithm.Name;
297 _baseAlgorithm.Name = value;
304 public HashSet<string>
Tags
308 return _baseAlgorithm.Tags;
312 _baseAlgorithm.Tags = value;
323 _baseAlgorithm.NameUpdated += value;
328 _baseAlgorithm.NameUpdated -= value;
335 public event AlgorithmEvent<HashSet<string>>
TagsUpdated
339 _baseAlgorithm.TagsUpdated += value;
344 _baseAlgorithm.TagsUpdated -= value;
367 return _baseAlgorithm.RunTimeError;
379 public ConcurrentDictionary<string, string>
RuntimeStatistics => _baseAlgorithm.RuntimeStatistics;
440 return _baseAlgorithm.Status;
480 _baseAlgorithm.InsightsGenerated += value;
485 _baseAlgorithm.InsightsGenerated -= value;
507 _baseAlgorithm.ProjectId = value;
511 return _baseAlgorithm.ProjectId;
518 public DateTime
Time => _baseAlgorithm.Time;
523 public DateTimeZone
TimeZone => _baseAlgorithm.TimeZone;
544 public DateTime
UtcTime => _baseAlgorithm.UtcTime;
581 => _baseAlgorithm.AddSecurity(securityType, symbol, resolution, market, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
599 => _baseAlgorithm.AddSecurity(symbol, resolution, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
611 bool extendedMarketHours =
false)
612 => _baseAlgorithm.AddFutureContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
624 => _baseAlgorithm.AddOptionContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
632 _baseAlgorithm.OnEndOfTimeStep();
639 public void Debug(
string message) => _baseAlgorithm.Debug(message);
645 public void Error(
string message) => _baseAlgorithm.Error(message);
651 public void AddChart(
Chart chart) => _baseAlgorithm.AddChart(chart);
658 public IEnumerable<Chart>
GetChartUpdates(
bool clearChartData =
false) => _baseAlgorithm.GetChartUpdates(clearChartData);
663 public bool GetLocked() => _baseAlgorithm.GetLocked();
668 public IReadOnlyDictionary<string, string>
GetParameters() => _baseAlgorithm.GetParameters();
677 public string GetParameter(
string name,
string defaultValue =
null) => _baseAlgorithm.GetParameter(name, defaultValue);
686 public int GetParameter(
string name,
int defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
695 public double GetParameter(
string name,
double defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
704 public decimal
GetParameter(
string name, decimal defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
721 public List<OrderTicket>
Liquidate(
Symbol symbol =
null,
bool asynchronous =
false,
string tag =
"Liquidated",
IOrderProperties orderProperties =
null) => _baseAlgorithm.Liquidate(symbol, asynchronous, tag, orderProperties);
727 public void Log(
string message) => _baseAlgorithm.Log(message);
734 _onBrokerageDisconnect();
742 _onBrokerageMessage(messageEvent);
750 _onBrokerageReconnect();
774 _baseAlgorithm.OnFrameworkData(slice);
792 _onDividends(dividends);
801 _onDelistings(delistings);
810 _onSymbolChangedEvents(symbolsChanged);
827 [Obsolete(
"This method is deprecated. Please use this overload: OnEndOfDay(Symbol symbol)")]
836 catch (PythonException exception)
838 if (!exception.Message.Contains(
"OnEndOfDay() missing 1 required positional argument"))
840 _baseAlgorithm.SetRunTimeError(exception);
861 catch (PythonException exception)
863 if (!exception.Message.Contains(
"OnEndOfDay() takes 1 positional argument but 2 were given"))
865 _baseAlgorithm.SetRunTimeError(exception);
880 if (_onMarginCall !=
null)
883 if (result ==
null || !result.IsIterable())
885 throw new Exception(
"OnMarginCall must return a non-empty list of SubmitOrderRequest");
890 using var iterator = result.GetIterator();
891 foreach (PyObject pyRequest
in iterator)
894 if (TryConvert(pyRequest, out request))
896 requests.Add(request);
901 if (requests.Count == 0)
903 throw new Exception(
"OnMarginCall must return a non-empty list of SubmitOrderRequest");
914 _onMarginCallWarning();
924 _onOrderEvent(newEvent);
934 return _onCommand(data);
945 return _baseAlgorithm.SubmitOrderRequest(request);
955 _onAssignmentOrderEvent(assignmentEvent);
964 _onSecuritiesChanged(changes);
973 _onFrameworkSecuritiesChanged(changes);
982 _baseAlgorithm.PostInitialize();
1004 public void SetAlgorithmId(
string algorithmId) => _baseAlgorithm.SetAlgorithmId(algorithmId);
1031 public void SetAccountCurrency(
string accountCurrency, decimal? startingCash =
null) => _baseAlgorithm.SetAccountCurrency(accountCurrency, startingCash);
1037 public void SetCash(decimal startingCash) => _baseAlgorithm.SetCash(startingCash);
1045 public void SetCash(
string symbol, decimal startingCash, decimal conversionRate = 0) => _baseAlgorithm.SetCash(symbol, startingCash, conversionRate);
1051 public void SetDateTime(DateTime time) => _baseAlgorithm.SetDateTime(time);
1058 public void SetStartDate(DateTime start) => _baseAlgorithm.SetStartDate(start);
1065 public void SetEndDate(DateTime end) => _baseAlgorithm.SetEndDate(end);
1079 public void SetRunTimeError(Exception exception) => _baseAlgorithm.SetRunTimeError(exception);
1086 _baseAlgorithm.SetFinishedWarmingUp();
1102 public void SetLiveMode(
bool live) => _baseAlgorithm.SetLiveMode(live);
1119 public void SetLocked() => _baseAlgorithm.SetLocked();
1125 public void SetMaximumOrders(
int max) => _baseAlgorithm.SetMaximumOrders(max);
1131 public void SetParameters(Dictionary<string, string> parameters) => _baseAlgorithm.SetParameters(parameters);
1140 private bool TryConvert<T>(PyObject pyObject, out T result)
1142 result =
default(T);
1143 var type = (Type)pyObject.GetPythonType().AsManagedObject(typeof(Type));
1145 if (type == typeof(T))
1147 result = (T)pyObject.AsManagedObject(typeof(T));
1150 return type == typeof(T);
1159 if (_algorithm ==
null)
1161 return base.ToString();
1165 return _algorithm.Repr();
1175 _baseAlgorithm.SetCurrentSlice(
new PythonSlice(slice));
1182 public void SetApi(
IApi api) => _baseAlgorithm.SetApi(api);
1201 return _baseAlgorithm.Shortable(symbol, shortQuantity, updateOrderId);
1213 return _baseAlgorithm.ShortableQuantity(symbol);
1230 public string Ticker(
Symbol symbol) => _baseAlgorithm.Ticker(symbol);
1238 _baseAlgorithm.SetName(name);
1247 _baseAlgorithm.AddTag(tag);
1256 _baseAlgorithm.SetTags(tags);