Files
2026-07-13 13:02:50 +08:00

179 lines
7.7 KiB
C#

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using NodaTime;
using QuantConnect.Data;
using QuantConnect.Util;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Data.Market;
using System.Collections.Generic;
using QuantConnect.Tests.Engine.DataFeeds;
namespace QuantConnect.Tests.Brokerages
{
public class TestsHelpers
{
public static Security GetSecurity(decimal price = 1m, SecurityType securityType = SecurityType.Crypto, Resolution resolution = Resolution.Minute, string symbol = "BTCUSD", string market = Market.Coinbase, string quoteCurrency = "USD", bool marketAlwaysOpen = true)
{
var config = CreateConfig(symbol, market, securityType, resolution);
var marketHours = marketAlwaysOpen
? SecurityExchangeHours.AlwaysOpen(TimeZones.Utc)
: MarketHoursDatabase.FromDataFolder().GetExchangeHours(config);
return new Security(
marketHours,
config,
new Cash(quoteCurrency, 1000, price),
#pragma warning disable CS0618
SymbolPropertiesDatabase.FromDataFolder().GetSymbolProperties(market, config.Symbol, securityType, quoteCurrency),
#pragma warning restore CS0618
ErrorCurrencyConverter.Instance,
RegisteredSecurityDataTypesProvider.Null,
new SecurityCache()
);
}
private static SubscriptionDataConfig CreateConfig(string symbol, string market, SecurityType securityType = SecurityType.Crypto, Resolution resolution = Resolution.Minute)
{
Symbol actualSymbol;
switch (securityType)
{
case SecurityType.FutureOption:
actualSymbol = Symbols.CreateFutureOptionSymbol(Symbols.CreateFutureSymbol(symbol, new DateTime(2020, 4, 28)), OptionRight.Call,
1000, new DateTime(2020, 3, 26));
break;
case SecurityType.Option:
actualSymbol = Symbols.CreateOptionSymbol(symbol, OptionRight.Call, 1000, new DateTime(2020, 3, 26));
break;
case SecurityType.IndexOption:
var index = Symbols.CreateIndexSymbol(symbol);
actualSymbol = Symbol.CreateOption(index, index.ID.Market, SecurityType.IndexOption.DefaultOptionStyle(), OptionRight.Call, 6500m, new(2026, 04, 13));
break;
default:
actualSymbol = Symbol.Create(symbol, securityType, market);
break;
}
return new SubscriptionDataConfig(typeof(TradeBar), actualSymbol, resolution, TimeZones.Utc, TimeZones.Utc, false, true, false);
}
public static HistoryRequest GetHistoryRequest(Symbol symbol, DateTime startDateTime, DateTime endDateTime, Resolution resolution, TickType tickType, DateTimeZone dateTimeZone = null)
{
if (startDateTime > endDateTime)
{
throw new ArgumentException("The startDateTime is greater then endDateTime");
}
if (dateTimeZone == null)
{
dateTimeZone = TimeZones.NewYork;
}
var dataType = LeanData.GetDataType(resolution, tickType);
return new HistoryRequest(
startDateTime,
endDateTime,
dataType,
symbol,
resolution,
SecurityExchangeHours.AlwaysOpen(dateTimeZone),
dateTimeZone,
null,
false,
false,
DataNormalizationMode.Raw,
tickType
);
}
public static IEnumerable<DateTimeZone> GetTimeZones()
{
yield return TimeZones.NewYork;
yield return TimeZones.EasternStandard;
yield return TimeZones.London;
yield return TimeZones.HongKong;
yield return TimeZones.Tokyo;
yield return TimeZones.Rome;
yield return TimeZones.Sydney;
yield return TimeZones.Vancouver;
yield return TimeZones.Toronto;
yield return TimeZones.Chicago;
yield return TimeZones.LosAngeles;
yield return TimeZones.Phoenix;
yield return TimeZones.Auckland;
yield return TimeZones.Moscow;
yield return TimeZones.Madrid;
yield return TimeZones.BuenosAires;
yield return TimeZones.Brisbane;
yield return TimeZones.SaoPaulo;
yield return TimeZones.Cairo;
yield return TimeZones.Johannesburg;
yield return TimeZones.Anchorage;
yield return TimeZones.Denver;
yield return TimeZones.Detroit;
yield return TimeZones.MexicoCity;
yield return TimeZones.Jerusalem;
yield return TimeZones.Shanghai;
yield return TimeZones.Melbourne;
yield return TimeZones.Amsterdam;
yield return TimeZones.Athens;
yield return TimeZones.Berlin;
yield return TimeZones.Bucharest;
yield return TimeZones.Dublin;
yield return TimeZones.Helsinki;
yield return TimeZones.Istanbul;
yield return TimeZones.Minsk;
yield return TimeZones.Paris;
yield return TimeZones.Zurich;
yield return TimeZones.Honolulu;
yield return TimeZones.Kolkata;
}
public static SecurityManager InitializeSecurity(SecurityType securityType, params (Symbol symbol, decimal averagePrice, decimal quantity)[] equityQuantity)
{
var algorithm = new AlgorithmStub();
foreach (var (symbol, averagePrice, quantity) in equityQuantity)
{
switch (securityType)
{
case SecurityType.Equity:
algorithm.AddEquity(symbol.Value).Holdings.SetHoldings(averagePrice, quantity);
break;
case SecurityType.Option:
algorithm.AddOptionContract(symbol).Holdings.SetHoldings(averagePrice, quantity);
break;
default:
throw new NotImplementedException($"{nameof(TestsHelpers)}.{nameof(InitializeSecurity)}: uses not implemented {securityType} security type.");
}
}
return algorithm.Securities;
}
public static Order CreateNewOrderByOrderType(OrderType orderType, Symbol symbol, decimal orderQuantity, GroupOrderManager groupOrderManager = null) => orderType switch
{
OrderType.Market => new MarketOrder(symbol, orderQuantity, new DateTime(default)),
OrderType.ComboMarket => new ComboMarketOrder(symbol, orderQuantity, new DateTime(default), groupOrderManager),
OrderType.ComboLimit => new ComboLimitOrder(symbol, orderQuantity, 80m, new DateTime(default), groupOrderManager),
_ => throw new NotImplementedException()
};
}
}