Skip to content

Commit

Permalink
Standarize implementation (#5)
Browse files Browse the repository at this point in the history
* Standarize implementation

- Standarize implementation. See QuantConnect/Lean#7837
- Adjust and fix example algorithms

* Minor tz tweak
  • Loading branch information
Martin-Molinero authored Mar 12, 2024
1 parent 7a83e9e commit d2fc0b0
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 20 deletions.
21 changes: 14 additions & 7 deletions CoinGeckoUniverse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
*
*/

using NodaTime;
using QuantConnect.Data;
using QuantConnect.Data.UniverseSelection;
using System;
using System.Globalization;
using System.IO;
Expand All @@ -24,7 +26,7 @@ namespace QuantConnect.DataSource
/// <summary>
/// Universe Selection Data for Coin Gecko data which contains Price, Volume, and Market Cap in USD for cryptocurrencies
/// </summary>
public class CoinGeckoUniverse : CoinGecko
public class CoinGeckoUniverse : BaseDataCollection
{
/// <summary>
/// Return the URL string source of the file. This will be converted to a stream
Expand All @@ -43,7 +45,8 @@ public override SubscriptionDataSource GetSource(SubscriptionDataConfig config,
"universe",
$"{date.ToStringInvariant(DateFormat.EightCharacter)}.csv"
),
SubscriptionTransportMedium.LocalFile
SubscriptionTransportMedium.LocalFile,
FileFormat.FoldingCollection
);
}

Expand All @@ -59,9 +62,9 @@ public override BaseData Reader(SubscriptionDataConfig config, string line, Date
{
var csv = line.Split(',');
var coin = csv[0].ToUpperInvariant();
var sid = SecurityIdentifier.GenerateBase(typeof(CoinGeckoUniverse), coin, Market.USA);
var sid = SecurityIdentifier.GenerateBase(typeof(CoinGecko), coin, Market.USA);

return new CoinGeckoUniverse
return new CoinGecko
{
Symbol = new Symbol(sid, coin),
EndTime = date,
Expand All @@ -82,10 +85,14 @@ public override BaseData Clone()
Symbol = Symbol,
Time = Time,
EndTime = EndTime,
MarketCap = MarketCap,
Value = Value,
Volume = Volume
Data = Data
};
}

/// <summary>
/// Specifies the data time zone for this data type. This is useful for custom data types
/// </summary>
/// <returns>The <see cref="T:NodaTime.DateTimeZone" /> of this data type</returns>
public override DateTimeZone DataTimeZone() => DateTimeZone.Utc;
}
}
20 changes: 17 additions & 3 deletions CoinGeckoUniverseSelectionAlgorithm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,32 @@ public override void Initialize()
SetCash(100000);

// add a custom universe data source (defaults to usa-equity)
AddUniverse<CoinGeckoUniverse>("CoinGeckoUniverse", Resolution.Daily, data =>
var universe = AddUniverse<CoinGeckoUniverse>("CoinGeckoUniverse", Resolution.Daily, data =>
{
foreach (var datum in data)
foreach (CoinGecko datum in data)
{
Debug($"{datum.Coin},{datum.MarketCap},{datum.Price}");
}

// define our selection criteria
return (from d in data
return (from CoinGecko d in data
orderby d.MarketCap descending
select d.CreateSymbol(Market.GDAX, "USD", SecurityType.Crypto)).Take(3);
});

var history = History(universe, 2).ToList();
if (history.Count != 2)
{
throw new Exception($"Unexpected historical data count!");
}
foreach (var dataForDate in history)
{
var coarseData = dataForDate.ToList();
if (coarseData.Count < 2)
{
throw new Exception($"Unexpected historical universe data!");
}
}
}

/// <summary>
Expand Down
12 changes: 10 additions & 2 deletions CoinGeckoUniverseSelectionAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
### <summary>
### Example algorithm using the custom data type as a source of alpha
### </summary>
class CoinGeckoUniverseSelectionAlgorithm(QCAlgorithm):
class CoinGeckoUniverseSelectionAlgorithm(QCAlgorithm):
def Initialize(self):
''' Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. '''

Expand All @@ -28,7 +28,15 @@ def Initialize(self):
self.SetCash(100000);

# add a custom universe data source
self.AddUniverse(CoinGeckoUniverse, "CoinGeckoUniverse", Resolution.Daily, self.UniverseSelection)
universe = self.AddUniverse(CoinGeckoUniverse, "CoinGeckoUniverse", Resolution.Daily, self.UniverseSelection)

history = self.History(universe, TimeSpan(2, 0, 0, 0))
if len(history) != 2:
raise ValueError(f"Unexpected history count {len(history)}! Expected 2")

for dataForDate in history:
if len(dataForDate) < 2:
raise ValueError(f"Unexpected historical universe data!")

def UniverseSelection(self, data):
''' Selected the securities
Expand Down
12 changes: 6 additions & 6 deletions CoinGeckoUniverseSelectionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ public class CoinGeckoUniverseSelectionModel : UniverseSelectionModel
{
private Universe _universe;
private UniverseSettings _universeSettings;
private readonly Func<IEnumerable<CoinGeckoUniverse>, IEnumerable<Symbol>> _selector;
private readonly Func<IEnumerable<CoinGecko>, IEnumerable<Symbol>> _selector;

/// <summary>
/// Initializes a new instance of the <see cref="CoinGeckoUniverseSelectionModel"/> class
/// </summary>
/// <param name="universeSettings">The settings used for new subscriptions generated by this universe</param>
/// <param name="selector">Returns the symbols that should be included in the universe</param>
public CoinGeckoUniverseSelectionModel(
Func<IEnumerable<CoinGeckoUniverse>, IEnumerable<Symbol>> selector,
Func<IEnumerable<CoinGecko>, IEnumerable<Symbol>> selector,
UniverseSettings universeSettings = null)
{
_universeSettings = universeSettings;
Expand All @@ -57,7 +57,7 @@ public CoinGeckoUniverseSelectionModel(
PyObject selector,
UniverseSettings universeSettings = null
)
: this(selector.ConvertPythonUniverseFilterFunction<CoinGeckoUniverse>(), universeSettings)
: this(selector.ConvertPythonUniverseFilterFunction<CoinGecko>(), universeSettings)
{
}

Expand All @@ -66,7 +66,7 @@ public CoinGeckoUniverseSelectionModel(
/// </summary>
/// <param name="universeSettings">The settings used for new subscriptions generated by this universe</param>
public CoinGeckoUniverseSelectionModel(UniverseSettings universeSettings = null)
: this((Func<IEnumerable<CoinGeckoUniverse>, IEnumerable<Symbol>>)null, universeSettings)
: this((Func<IEnumerable<CoinGecko>, IEnumerable<Symbol>>)null, universeSettings)
{
_universeSettings = universeSettings;
}
Expand All @@ -78,7 +78,7 @@ public CoinGeckoUniverseSelectionModel(UniverseSettings universeSettings = null)
/// <param name="data">The CoinGecko Universe data used to perform filtering</param>
/// <exception cref="ArgumentNullException">The Selector cannot be null</exception>
/// <returns>An enumerable of symbols passing the filter</returns>
public virtual IEnumerable<Symbol> Selector(QCAlgorithm algorithm, IEnumerable<CoinGeckoUniverse> data)
public virtual IEnumerable<Symbol> Selector(QCAlgorithm algorithm, IEnumerable<CoinGecko> data)
{
if (_selector != null)
{
Expand Down Expand Up @@ -118,7 +118,7 @@ public override IEnumerable<Universe> CreateUniverses(QCAlgorithm algorithm)
.SetEntryAlwaysOpen(config.Market, ticker, config.SecurityType, config.DataTimeZone);

_universe = new FuncUniverse(config, _universeSettings ??= algorithm.UniverseSettings,
d => Selector(algorithm, d.OfType<CoinGeckoUniverse>()));
d => Selector(algorithm, d.OfType<CoinGecko>()));

yield return _universe;
}
Expand Down
2 changes: 1 addition & 1 deletion CoinGeckoUniverseSelectionModelAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
### <summary>
### Example algorithm using the custom data type as a source of alpha
### </summary>
class CoinGeckoUniverseSelectionModelAlgorithm(QCAlgorithm):
class CoinGeckoUniverseSelectionModelAlgorithm(QCAlgorithm):
def Initialize(self):
''' Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. '''

Expand Down
2 changes: 1 addition & 1 deletion QuantConnect.DataSource.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<ItemGroup>
<PackageReference Include="QuantConnect.Algorithm.Framework" Version="2.5.*" />
<PackageReference Include="QuantConnect.Common" Version="2.5.*" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit d2fc0b0

Please sign in to comment.