34 using System.Collections.Concurrent;
35 using System.Collections.Generic;
48 private readonly PyObject _algorithm;
49 private readonly dynamic _onData;
50 private readonly dynamic _onMarginCall;
55 private dynamic _onBrokerageDisconnect;
56 private dynamic _onBrokerageMessage;
57 private dynamic _onBrokerageReconnect;
58 private dynamic _onSplits;
59 private dynamic _onDividends;
60 private dynamic _onDelistings;
61 private dynamic _onSymbolChangedEvents;
62 private dynamic _onEndOfDay;
63 private dynamic _onMarginCallWarning;
64 private dynamic _onOrderEvent;
65 private dynamic _onAssignmentOrderEvent;
66 private dynamic _onSecuritiesChanged;
67 private dynamic _onFrameworkSecuritiesChanged;
91 Logging.Log.Trace($
"AlgorithmPythonWrapper(): Python version {PythonEngine.Version}: Importing python module {moduleName}");
93 var module = Py.Import(moduleName);
95 Logging.Log.Trace($
"AlgorithmPythonWrapper(): {moduleName} successfully imported.");
97 var pyList = module.Dir();
98 foreach (var name
in pyList)
101 var attr = module.GetAttr(name.ToString());
102 var repr = attr.Repr().GetStringBetweenChars(
'\'',
'\'');
104 if (repr.StartsWith(moduleName) &&
105 attr.TryConvert(out type,
true) &&
108 Logging.Log.Trace(
"AlgorithmPythonWrapper(): Creating IAlgorithm instance.");
110 _algorithm = attr.Invoke();
112 var dynAlgorithm = _algorithm as dynamic;
115 dynAlgorithm.SetPandasConverter();
118 _baseAlgorithm = dynAlgorithm.AsManagedObject(type);
122 _onData = _algorithm.GetPythonMethod(
"OnData");
124 _onMarginCall = _algorithm.GetPythonMethod(
"OnMarginCall");
126 PyObject endOfDayMethod = _algorithm.GetPythonMethod(
"OnEndOfDay");
127 if (endOfDayMethod !=
null)
131 var argCount = endOfDayMethod.GetPythonArgCount();
148 _onBrokerageDisconnect = _algorithm.GetMethod(
"OnBrokerageDisconnect");
149 _onBrokerageMessage = _algorithm.GetMethod(
"OnBrokerageMessage");
150 _onBrokerageReconnect = _algorithm.GetMethod(
"OnBrokerageReconnect");
151 _onSplits = _algorithm.GetMethod(
"OnSplits");
152 _onDividends = _algorithm.GetMethod(
"OnDividends");
153 _onDelistings = _algorithm.GetMethod(
"OnDelistings");
154 _onSymbolChangedEvents = _algorithm.GetMethod(
"OnSymbolChangedEvents");
155 _onEndOfDay = _algorithm.GetMethod(
"OnEndOfDay");
156 _onMarginCallWarning = _algorithm.GetMethod(
"OnMarginCallWarning");
157 _onOrderEvent = _algorithm.GetMethod(
"OnOrderEvent");
158 _onAssignmentOrderEvent = _algorithm.GetMethod(
"OnAssignmentOrderEvent");
159 _onSecuritiesChanged = _algorithm.GetMethod(
"OnSecuritiesChanged");
160 _onFrameworkSecuritiesChanged = _algorithm.GetMethod(
"OnFrameworkSecuritiesChanged");
167 if (_algorithm ==
null)
169 throw new Exception(
"Please ensure that one class inherits from QCAlgorithm.");
177 e = interpreter.
Interpret(e, interpreter);
179 throw new Exception($
"AlgorithmPythonWrapper(): {interpreter.GetExceptionMessageHeader(e)}");
202 return _baseAlgorithm.BrokerageMessageHandler;
229 public ConcurrentQueue<string>
DebugMessages => _baseAlgorithm.DebugMessages;
234 public DateTime
EndDate => _baseAlgorithm.EndDate;
239 public ConcurrentQueue<string>
ErrorMessages => _baseAlgorithm.ErrorMessages;
248 return _baseAlgorithm.HistoryProvider;
280 public ConcurrentQueue<string>
LogMessages => _baseAlgorithm.LogMessages;
290 return _baseAlgorithm.Name;
294 _baseAlgorithm.Name = value;
301 public HashSet<string>
Tags
305 return _baseAlgorithm.Tags;
309 _baseAlgorithm.Tags = value;
320 _baseAlgorithm.NameUpdated += value;
325 _baseAlgorithm.NameUpdated -= value;
332 public event AlgorithmEvent<HashSet<string>>
TagsUpdated
336 _baseAlgorithm.TagsUpdated += value;
341 _baseAlgorithm.TagsUpdated -= value;
364 return _baseAlgorithm.RunTimeError;
376 public ConcurrentDictionary<string, string>
RuntimeStatistics => _baseAlgorithm.RuntimeStatistics;
437 return _baseAlgorithm.Status;
477 _baseAlgorithm.InsightsGenerated += value;
482 _baseAlgorithm.InsightsGenerated -= value;
504 _baseAlgorithm.ProjectId = value;
508 return _baseAlgorithm.ProjectId;
515 public DateTime
Time => _baseAlgorithm.Time;
520 public DateTimeZone
TimeZone => _baseAlgorithm.TimeZone;
541 public DateTime
UtcTime => _baseAlgorithm.UtcTime;
578 => _baseAlgorithm.AddSecurity(securityType, symbol, resolution, market, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode);
596 => _baseAlgorithm.AddSecurity(symbol, resolution, fillForward, leverage, extendedMarketHours, dataMappingMode, dataNormalizationMode, contractDepthOffset);
608 bool extendedMarketHours =
false)
609 => _baseAlgorithm.AddFutureContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
621 => _baseAlgorithm.AddOptionContract(symbol, resolution, fillForward, leverage, extendedMarketHours);
629 _baseAlgorithm.OnEndOfTimeStep();
636 public void Debug(
string message) => _baseAlgorithm.Debug(message);
642 public void Error(
string message) => _baseAlgorithm.Error(message);
648 public void AddChart(
Chart chart) => _baseAlgorithm.AddChart(chart);
655 public IEnumerable<Chart>
GetChartUpdates(
bool clearChartData =
false) => _baseAlgorithm.GetChartUpdates(clearChartData);
660 public bool GetLocked() => _baseAlgorithm.GetLocked();
665 public IReadOnlyDictionary<string, string>
GetParameters() => _baseAlgorithm.GetParameters();
674 public string GetParameter(
string name,
string defaultValue =
null) => _baseAlgorithm.GetParameter(name, defaultValue);
683 public int GetParameter(
string name,
int defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
692 public double GetParameter(
string name,
double defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
701 public decimal
GetParameter(
string name, decimal defaultValue) => _baseAlgorithm.GetParameter(name, defaultValue);
717 public List<int>
Liquidate(
Symbol symbolToLiquidate =
null,
string tag =
"Liquidated") => _baseAlgorithm.Liquidate(symbolToLiquidate, tag);
723 public void Log(
string message) => _baseAlgorithm.Log(message);
730 _onBrokerageDisconnect();
738 _onBrokerageMessage(messageEvent);
746 _onBrokerageReconnect();
770 _baseAlgorithm.OnFrameworkData(slice);
788 _onDividends(dividends);
797 _onDelistings(delistings);
806 _onSymbolChangedEvents(symbolsChanged);
823 [Obsolete(
"This method is deprecated. Please use this overload: OnEndOfDay(Symbol symbol)")]
832 catch (PythonException exception)
834 if (!exception.Message.Contains(
"OnEndOfDay() missing 1 required positional argument"))
836 _baseAlgorithm.SetRunTimeError(exception);
857 catch (PythonException exception)
859 if (!exception.Message.Contains(
"OnEndOfDay() takes 1 positional argument but 2 were given"))
861 _baseAlgorithm.SetRunTimeError(exception);
875 var result = method.Invoke<PyObject>(requests);
877 if (_onMarginCall !=
null)
880 if (result ==
null || !result.IsIterable())
882 throw new Exception(
"OnMarginCall must return a non-empty list of SubmitOrderRequest");
887 using var iterator = result.GetIterator();
888 foreach (PyObject pyRequest
in iterator)
891 if (TryConvert(pyRequest, out request))
893 requests.Add(request);
898 if (requests.Count == 0)
900 throw new Exception(
"OnMarginCall must return a non-empty list of SubmitOrderRequest");
911 _onMarginCallWarning();
921 _onOrderEvent(newEvent);
932 return _baseAlgorithm.SubmitOrderRequest(request);
942 _onAssignmentOrderEvent(assignmentEvent);
951 _onSecuritiesChanged(changes);
960 _onFrameworkSecuritiesChanged(changes);
969 _baseAlgorithm.PostInitialize();
991 public void SetAlgorithmId(
string algorithmId) => _baseAlgorithm.SetAlgorithmId(algorithmId);
1018 public void SetAccountCurrency(
string accountCurrency, decimal? startingCash =
null) => _baseAlgorithm.SetAccountCurrency(accountCurrency, startingCash);
1024 public void SetCash(decimal startingCash) => _baseAlgorithm.SetCash(startingCash);
1032 public void SetCash(
string symbol, decimal startingCash, decimal conversionRate = 0) => _baseAlgorithm.SetCash(symbol, startingCash, conversionRate);
1038 public void SetDateTime(DateTime time) => _baseAlgorithm.SetDateTime(time);
1045 public void SetStartDate(DateTime start) => _baseAlgorithm.SetStartDate(start);
1052 public void SetEndDate(DateTime end) => _baseAlgorithm.SetEndDate(end);
1066 public void SetRunTimeError(Exception exception) => _baseAlgorithm.SetRunTimeError(exception);
1073 _baseAlgorithm.SetFinishedWarmingUp();
1089 public void SetLiveMode(
bool live) => _baseAlgorithm.SetLiveMode(live);
1106 public void SetLocked() => _baseAlgorithm.SetLocked();
1112 public void SetMaximumOrders(
int max) => _baseAlgorithm.SetMaximumOrders(max);
1118 public void SetParameters(Dictionary<string, string> parameters) => _baseAlgorithm.SetParameters(parameters);
1127 private bool TryConvert<T>(PyObject pyObject, out T result)
1129 result =
default(T);
1130 var type = (Type)pyObject.GetPythonType().AsManagedObject(typeof(Type));
1132 if (type == typeof(T))
1134 result = (T)pyObject.AsManagedObject(typeof(T));
1137 return type == typeof(T);
1146 if (_algorithm ==
null)
1148 return base.ToString();
1152 return _algorithm.Repr();
1162 _baseAlgorithm.SetCurrentSlice(
new PythonSlice(slice));
1169 public void SetApi(
IApi api) => _baseAlgorithm.SetApi(api);
1188 return _baseAlgorithm.Shortable(symbol, shortQuantity, updateOrderId);
1200 return _baseAlgorithm.ShortableQuantity(symbol);
1217 public string Ticker(
Symbol symbol) => _baseAlgorithm.Ticker(symbol);
1225 _baseAlgorithm.SetName(name);
1234 _baseAlgorithm.AddTag(tag);
1243 _baseAlgorithm.SetTags(tags);