├── .gitattributes ├── .github └── workflows │ └── build.yml ├── .gitignore ├── AlphaPortfolioBuilding └── SortinoOptimization │ ├── calculations.py │ ├── factors.py │ ├── fetch_data.py │ ├── main.py │ ├── plotting.py │ ├── research.ipynb │ └── statistics.py ├── AlphaStream ├── .ipynb_checkpoints │ └── QuantConnectAlphaStreamsNotebook-checkpoint.ipynb ├── AlphaInsightsStreamClient.py ├── AlphaStreamClient.py ├── AlphaStreamEventClient.py ├── AlphaStreamRestClient.py ├── Models │ ├── Alpha.py │ ├── AlphaBacktestResult.py │ ├── AlphaResultPackage.py │ ├── Author.py │ ├── Bid.py │ ├── BidReponse.py │ ├── BidResult.py │ ├── HeartbeatPackage.py │ ├── Insight.py │ ├── Order.py │ ├── OrderEnums.py │ ├── OrderEvent.py │ ├── Project.py │ ├── RuntimeError.py │ ├── Symbol.py │ ├── Tag.py │ └── __init__.py ├── Properties │ └── AssemblyInfo.cs ├── QuantConnect.AlphaStream.AlphaAnalysisNotebook.ipynb ├── QuantConnect.AlphaStream.CompositeAlphaAnalysis.ipynb ├── QuantConnect.AlphaStream.Python.pyproj ├── QuantConnect │ ├── __init__.py │ └── api.py ├── QuantConnectAlphaStreamsNotebook.ipynb ├── README.rst ├── Requests │ ├── AddInsightsStreamRequest.py │ ├── CreateBidPriceRequest.py │ ├── GetAlphaBidRequest.py │ ├── GetAlphaByIdRequest.py │ ├── GetAlphaEquityCurveRequest.py │ ├── GetAlphaErrorsRequest.py │ ├── GetAlphaInsightsRequest.py │ ├── GetAlphaListRequest.py │ ├── GetAlphaOrdersRequest.py │ ├── GetAlphaTagsRequest.py │ ├── GetAuthorByIdRequest.py │ ├── RemoveAlphaBidRequest.py │ ├── SearchAlphasRequest.py │ ├── SearchAuthorsRequest.py │ └── __init__.py ├── Single Alpha Analysis │ ├── NAV.csv │ ├── RealAlpha_FullBacktest.csv │ ├── Single Alpha Analysis - Fractional Allocation.ipynb │ ├── Single Alpha Analysis - Unlimited Buying Power.ipynb │ └── Single Alpha Analysis.pdf ├── __init__.py ├── __version__.py ├── app.config ├── app.py ├── launch.bat └── packages.config ├── CHANGELOG.md ├── LICENSE ├── QuantConnect.API.Specification ├── QuantConnect_Alpha_0.3_swagger.yaml ├── QuantConnect_Alpha_0.4_swagger.yaml ├── QuantConnect_Alpha_0.5_swagger.yaml ├── QuantConnect_Alpha_0.6_swagger.yaml ├── QuantConnect_Alpha_0.7_swagger.yaml └── QuantConnect_Alpha_0.8_swagger.yaml ├── QuantConnect.AlphaStream.Demo ├── App.config ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── QuantConnect.AlphaStream.Demo.csproj ├── alpha-credentials.json └── config.json ├── QuantConnect.AlphaStream.Python.Tests ├── CreateBid.py ├── CreateReadConversation.py ├── GetAlphaById.py ├── GetAlphaEquityCurve.py ├── GetAlphaErrors.py ├── GetAlphaInsights.py ├── GetAlphaList.py ├── GetAlphaOrders.py ├── GetAlphaPrices.py ├── GetAlphaTags.py ├── SearchAlphas.py ├── SearchAuthors.py ├── StreamInsightsTest.py ├── StreamingOrderTests.py ├── SubscribeUnsubscribe.py ├── SymbolTests.py ├── TestData │ ├── AlphaAuthorTestData.txt │ └── InsightTestData.txt ├── config.json ├── runAllUnitTests.py └── test_config.py ├── QuantConnect.AlphaStream.Tests ├── AlphaCredentialsTest.cs ├── AlphaStreamClientTests.cs ├── AlphaStreamRestClientTests.cs ├── Credentials.cs ├── Infrastructure │ ├── DoubleUnixSecondsDateTimeJsonConverterTests.cs │ ├── HyphenSeparatedComplexQueryParameterNamingConventionTests.cs │ └── TimeTests.cs ├── Models │ ├── AlphaStreamInsightJsonConverterTests.cs │ └── Orders │ │ └── AlphaStreamOrderEventTests.cs ├── Properties │ └── AssemblyInfo.cs ├── QuantConnect.AlphaStream.Tests.csproj ├── Setup.cs ├── alpha-credentials.json ├── app.config └── config.json ├── QuantConnect.AlphaStream.sln ├── QuantConnect.AlphaStream ├── AlphaCredentials.cs ├── AlphaInsightsStreamClient.cs ├── AlphaInsightsStreamCredentials.cs ├── AlphaStreamCredentials.cs ├── AlphaStreamEventClient.cs ├── AlphaStreamRestClient.cs ├── HeartbeatReceivedEventArgs.cs ├── IAlphaInsightsStreamClient.cs ├── IAlphaStreamClient.cs ├── IAlphaStreamRestClient.cs ├── Infrastructure │ ├── AlphaServiceException.cs │ ├── AlphaStreamInsightJsonConverter.cs │ ├── AttributeRequest.cs │ ├── BodyParameterAttribute.cs │ ├── EndpointAttribute.cs │ ├── HyphenSeparatedQueryParameterNamingConvention.cs │ ├── IQueryParameterNamingConvention.cs │ ├── IRequest.cs │ ├── ParameterAttribute.cs │ ├── PathParameterAttribute.cs │ ├── QueryParameterAttribute.cs │ ├── QueryParameterDescriptor.cs │ ├── RestRequestExtensions.cs │ ├── StringExtensions.cs │ └── Time.cs ├── InsightReceivedEventArgs.cs ├── Models │ ├── Alpha.cs │ ├── AlphaStatus.cs │ ├── AlphaStreamInsight.cs │ ├── ApiResponse.cs │ ├── Author.cs │ ├── Bid.cs │ ├── BidResponse.cs │ ├── BidResult.cs │ ├── DateRange.cs │ ├── EquityCurve.cs │ ├── InsightPackage.cs │ ├── NumberRange.cs │ ├── Orders │ │ ├── AlphaStreamOrder.cs │ │ └── AlphaStreamOrderEvent.cs │ ├── Project.cs │ ├── Range.cs │ ├── RuntimeError.cs │ ├── Source.cs │ └── Tag.cs ├── OrderReceivedEventArgs.cs ├── Properties │ └── AssemblyInfo.cs ├── QuantConnect.AlphaStream.csproj ├── Requests │ ├── AddAlphaStreamRequest.cs │ ├── AddInsightsStreamRequest.cs │ ├── AlphaStreamRequest.cs │ ├── CreateBidPriceRequest.cs │ ├── GetAlphaBidRequest.cs │ ├── GetAlphaByIdRequest.cs │ ├── GetAlphaEquityCurveRequest.cs │ ├── GetAlphaErrorsRequest.cs │ ├── GetAlphaInsightsRequest.cs │ ├── GetAlphaListRequest.cs │ ├── GetAlphaOrdersRequest.cs │ ├── GetAlphaTagsRequest.cs │ ├── GetAuthorByIdRequest.cs │ ├── RemoveAlphaBidRequest.cs │ ├── RemoveAlphaStreamRequest.cs │ ├── RemoveInsightsStreamRequest.cs │ ├── SearchAlphasRequest.cs │ └── SearchAuthorsRequest.cs └── app.config ├── QuantConnect.AlphaStreamsRunnerAlgorithm └── Python │ ├── AlphaStreamsAlphaModel.py │ ├── AlphaStreamsRunnerAlgorithm.py │ ├── AlphaStreamsSocket.py │ ├── BrokerageSupportedSecurities.py │ └── __init__.py ├── README.md └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | 65 | #these files are used in linux, so use just LF 66 | *.sh lf -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: ['*'] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-20.04 12 | container: 13 | image: quantconnect/lean:foundation 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Checkout Lean Same Branch 18 | id: lean-same-branch 19 | uses: actions/checkout@v2 20 | continue-on-error: true 21 | with: 22 | ref: ${{ github.ref }} 23 | repository: QuantConnect/Lean 24 | path: Lean 25 | 26 | - name: Checkout Lean Master 27 | if: steps.lean-same-branch.outcome != 'success' 28 | uses: actions/checkout@v2 29 | with: 30 | repository: QuantConnect/Lean 31 | path: Lean 32 | 33 | - name: Move Lean 34 | run: mv Lean ../Lean 35 | 36 | - name: BuildAlphaStreams 37 | run: dotnet build ./QuantConnect.AlphaStream/QuantConnect.AlphaStream.csproj /p:Configuration=Release /v:quiet /p:WarningLevel=1 38 | 39 | - name: BuildAlphaStreamsDemo 40 | run: dotnet build ./QuantConnect.AlphaStream.Demo/QuantConnect.AlphaStream.Demo.csproj /p:Configuration=Release /v:quiet /p:WarningLevel=1 41 | 42 | - name: BuildAlphaStreamsTests 43 | run: dotnet build ./QuantConnect.AlphaStream.Tests/QuantConnect.AlphaStream.Tests.csproj /p:Configuration=Release /v:quiet /p:WarningLevel=1 44 | -------------------------------------------------------------------------------- /AlphaPortfolioBuilding/SortinoOptimization/factors.py: -------------------------------------------------------------------------------- 1 | from clr import AddReference 2 | AddReference("QuantConnect.Research") 3 | from QuantConnect import * 4 | from QuantConnect.Research import QuantBook 5 | 6 | from abc import ABC, abstractmethod 7 | import pandas as pd 8 | import numpy as np 9 | from datetime import datetime, timedelta 10 | 11 | class Factor(ABC): 12 | """ 13 | Abstract base class used to create factors 14 | """ 15 | @abstractmethod 16 | def evaluate(equity_curve): 17 | """ 18 | Calculates the factor value using the provided equity curve. 19 | 20 | Input: 21 | - equity_curve 22 | The equity curve to calculate the factor on 23 | 24 | Returns the factor value when applied to the equity curve. 25 | """ 26 | raise Exception("evaluate method not implemented yet.") 27 | 28 | 29 | class Sortino(Factor): 30 | """ 31 | Sortino Ratio 32 | """ 33 | def evaluate(equity_curve): 34 | returns = equity_curve.pct_change().dropna() 35 | ann_ret = ((np.mean(returns) + 1) ** 252) - 1 36 | ann_down_std = np.std(returns.loc[returns < 0]) * np.sqrt(252) 37 | return ann_ret / ann_down_std if ann_down_std is not 0 else None 38 | 39 | 40 | class Beta(Factor): 41 | """ 42 | Beta 43 | """ 44 | benchmark_data = pd.DataFrame() 45 | 46 | @staticmethod 47 | def load_data(benchmark_security_id='SPY R735QTJ8XC9X', benchmark_name='*Benchmark*'): 48 | """ 49 | Loads the benchmark data so we can calculate the factor value 50 | 51 | Input: 52 | - benchmark_security_id 53 | Security ID of the benchmark security 54 | - benchmark_name 55 | The column name to use for the benchmark in the DataFrame that's loaded 56 | """ 57 | Beta.benchmark_data = pd.DataFrame() 58 | qb = QuantBook() 59 | benchmark_symbol = qb.Symbol(benchmark_security_id) 60 | 61 | # Load benchmark history 62 | history = qb.History(benchmark_symbol, datetime(1998, 1, 2), datetime.now(), Resolution.Daily) 63 | Beta.benchmark_data = history.loc[benchmark_symbol].close 64 | Beta.benchmark_data = Beta.benchmark_data.resample('D').mean().interpolate(method='linear', limit_area='inside') 65 | Beta.benchmark_data.name = benchmark_name 66 | 67 | def evaluate(equity_curve): 68 | # Get benchmark equity curve 69 | if Beta.benchmark_data.empty: 70 | Beta.load_data() 71 | start = equity_curve.index[0] 72 | end = equity_curve.index[-1] + timedelta(days=1) 73 | benchmark_equity_curve = Beta.benchmark_data.loc[start:end] 74 | 75 | # Calculate Beta 76 | equity_curve_returns = equity_curve.pct_change().dropna() 77 | benchmark_returns = benchmark_equity_curve.pct_change().dropna() 78 | equity_df = pd.concat([equity_curve_returns, benchmark_returns], axis=1) 79 | corr = equity_df.corr()[benchmark_equity_curve.name][0] 80 | std = equity_curve_returns.std() 81 | if std == 0: 82 | return np.nan 83 | std_ratio = benchmark_returns.std() / std 84 | return corr * std_ratio 85 | 86 | 87 | class Drawdown(Factor): 88 | """ 89 | Drawdown 90 | """ 91 | def evaluate(equity_curve): 92 | equity_curve = equity_curve.values 93 | i = np.argmax(np.maximum.accumulate(equity_curve) - equity_curve) 94 | if equity_curve[:i].size == 0: 95 | return np.nan 96 | j = np.argmax(equity_curve[:i]) 97 | return abs((equity_curve[i]/equity_curve[j]) - 1) #round(abs((equity_curve[i]/equity_curve[j]) - 1), 3) 98 | -------------------------------------------------------------------------------- /AlphaPortfolioBuilding/SortinoOptimization/fetch_data.py: -------------------------------------------------------------------------------- 1 | from clr import AddReference 2 | AddReference("QuantConnect.Research") 3 | from QuantConnect import * 4 | from QuantConnect.Research import QuantBook 5 | 6 | import pandas as pd 7 | from io import StringIO 8 | 9 | def get_live_equity_curves(alpha_id_by_name): 10 | """ 11 | Gathers the live equity curves of active alphas. We declare an alpha as 'inactive' 12 | if the last data point in its equity curve is older that the last data point in the 13 | equity curve of another alpha in the `alpha_id_by_name` dictionary. We truncate 14 | the start of the equity curves so that the resulting DataFrame has always atleast 15 | 2 live alphas running at each timestep. 16 | 17 | Input: 18 | - client 19 | Client used to communicate with alpha stream REST api 20 | - alpha_id_by_name 21 | Dictionary of alpha IDs, keyed by the alpha name 22 | 23 | Returns a DataFrame of normalized live equity curves for the active alphas. 24 | """ 25 | # Get equity curves into a DataFrame 26 | qb = QuantBook() 27 | url = "https://s3.amazonaws.com/alphastreams.quantconnect.com/alphas/equity-unified-live-factors.csv" 28 | csv = qb.Download(url) 29 | equity_curves = pd.read_csv(StringIO(csv)) 30 | equity_curves['Time'] = pd.to_datetime(equity_curves['Time']) 31 | equity_curves.set_index('Time', inplace=True) 32 | equity_curves = equity_curves[[alpha_id for alpha_id in alpha_id_by_name.values()]] 33 | equity_curves.columns = [alpha_name for alpha_name in alpha_id_by_name.keys()] 34 | equity_curves = equity_curves.resample('D').mean().interpolate(method='linear', limit_area='inside') 35 | 36 | # Drop inactive alphas 37 | inactive_alphas = equity_curves.iloc[-1].isna().values 38 | for alpha_name in equity_curves.columns[inactive_alphas]: 39 | print(f"'{alpha_name}' excluded because it's marked as inactive.") 40 | has_data = equity_curves.columns[~inactive_alphas] 41 | 42 | # Truncate start of history to when there are atleast 2 alphas 43 | equity_curves = equity_curves[has_data].dropna(thresh=2) 44 | 45 | # Normalize the equity curves 46 | normalized_curves = pd.DataFrame() 47 | for alpha_id in equity_curves.columns: 48 | alpha_equity = equity_curves[alpha_id].dropna() 49 | alpha_equity = alpha_equity / alpha_equity.iloc[0] 50 | normalized_curves = normalized_curves.join(alpha_equity, how = 'outer') 51 | 52 | return normalized_curves 53 | -------------------------------------------------------------------------------- /AlphaPortfolioBuilding/SortinoOptimization/main.py: -------------------------------------------------------------------------------- 1 | class LogicalFluorescentOrangeSalamander(QCAlgorithm): 2 | 3 | def Initialize(self): 4 | self.SetStartDate(2020, 10, 5) # Set Start Date 5 | self.SetCash(100000) # Set Strategy Cash 6 | # self.AddEquity("SPY", Resolution.Minute) 7 | 8 | 9 | def OnData(self, data): 10 | '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. 11 | Arguments: 12 | data: Slice object keyed by symbol containing the stock data 13 | ''' 14 | # if not self.Portfolio.Invested: 15 | # self.SetHoldings("SPY", 1) 16 | -------------------------------------------------------------------------------- /AlphaPortfolioBuilding/SortinoOptimization/plotting.py: -------------------------------------------------------------------------------- 1 | import calendar 2 | import matplotlib.pyplot as plt 3 | import pandas as pd 4 | 5 | def plot_allocations_over_time(allocations_over_time): 6 | """ 7 | Creates a plot to show the allocations given to each alpha over time. 8 | 9 | Input: 10 | - allocations_over_time 11 | A DataFrame which lists how much to allocate to each alpha over time 12 | """ 13 | f, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(16, 10)) 14 | 15 | # Calculate bar plot widths 16 | widths = [] 17 | for time, row in allocations_over_time.iterrows(): 18 | days_in_month = calendar.monthrange(time.year, time.month)[1] 19 | widths.append(days_in_month - time.day - 0.5) 20 | 21 | # Stacked bar plot 22 | ax1.set_title('Alpha Allocations Over Time') 23 | ax1.set_ylabel('Portfolio Weight (%)') 24 | x = allocations_over_time.index 25 | previous_allocations = [0] * allocations_over_time.shape[0] 26 | for alpha in allocations_over_time.columns: 27 | current_allocations = allocations_over_time[alpha].fillna(0) * 100 28 | ax1.bar(x, current_allocations, widths, bottom=previous_allocations, align='edge', label=alpha) 29 | previous_allocations = current_allocations + previous_allocations 30 | ax1.legend(allocations_over_time.columns, frameon=True, framealpha=0.7, facecolor='white') 31 | 32 | # Bar plot 33 | number_of_alphas_allocated_to = [] 34 | for time, row in allocations_over_time.iterrows(): 35 | number_of_alphas_allocated_to.append(len(row[row > 0])) 36 | ax2.bar(x, number_of_alphas_allocated_to, width=widths, align='edge') 37 | ax2.set_xlabel('Month') 38 | ax2.set_ylabel('Number of Alphas Allocated To') 39 | plt.xticks(rotation=-90) 40 | y_ticks = range(0, max(number_of_alphas_allocated_to)+1) 41 | ax2.yaxis.set_ticks(y_ticks) 42 | ax2.margins(0) 43 | plt.show() 44 | 45 | def plot_all_equity_curves(equity_curves, composite_equity_curve): 46 | """ 47 | Plot the equity curves and composite equity curve in a single line chart. 48 | 49 | Input: 50 | - equity_curves 51 | Equity curves of the alphas 52 | - composite_equity_curve 53 | Equity curve of the optimized portfolio 54 | """ 55 | all_curves = pd.DataFrame() 56 | all_curves = equity_curves.join(composite_equity_curve, how = 'outer') 57 | all_curves[equity_curves.columns].plot(figsize=(16, 6), c='grey') 58 | all_curves['*CompositeAlpha*'].plot(c='orange', linewidth=4) 59 | plt.legend(all_curves.columns) 60 | plt.title('Alpha Equity vs Optimized Portfolio Equity') 61 | plt.xlabel('Date') 62 | plt.ylabel('Normalized Equity') 63 | plt.show() 64 | -------------------------------------------------------------------------------- /AlphaPortfolioBuilding/SortinoOptimization/statistics.py: -------------------------------------------------------------------------------- 1 | from clr import AddReference 2 | AddReference("QuantConnect.Research") 3 | from QuantConnect import * 4 | from QuantConnect.Research import QuantBook 5 | from QuantConnect.Statistics import * 6 | from factors import Sortino, Drawdown 7 | 8 | from datetime import timedelta 9 | import pandas as pd 10 | 11 | def get_performance_statistics(composite_equity_curve, bechmark_security_id="SPY R735QTJ8XC9X"): 12 | """ 13 | Calculates several performance statistics on the composite equity curve. 14 | 15 | Input: 16 | - composite_equity_curve 17 | Equity curve of the optimized portfolio 18 | - bechmark_security_id 19 | Security ID of the benchmark to use in some of the statistic calculations (like Beta) 20 | 21 | Returns a DataFrame that lists the performance statistics of the composite equity curve. 22 | """ 23 | performance_statistics = {} 24 | daily_returns = list(composite_equity_curve.pct_change().dropna().values) 25 | 26 | # CompoundingAnnualPerformance 27 | start_equity = composite_equity_curve.iloc[0] 28 | end_equity = composite_equity_curve.iloc[-1] 29 | num_years = (composite_equity_curve.index[-1] - composite_equity_curve.index[0]).days / 365 30 | comp_annual_performance = Statistics.CompoundingAnnualPerformance(start_equity, end_equity, num_years) 31 | performance_statistics['CompoundingAnnualPerformance'] = "{:.2%}".format(comp_annual_performance) 32 | 33 | # AnnualPerformance 34 | performance_statistics['AnnualPerformance'] = Statistics.AnnualPerformance(daily_returns, 365) 35 | 36 | # AnnualVariance 37 | performance_statistics['AnnualVariance'] = Statistics.AnnualVariance(daily_returns, 365) 38 | 39 | # AnnualStandardDeviation 40 | performance_statistics['AnnualStandardDeviation'] = Statistics.AnnualStandardDeviation(daily_returns, 365) 41 | 42 | # Fetch daily benchmark returns 43 | qb = QuantBook() 44 | start_date = composite_equity_curve.index[0] - timedelta(days=5) # 5 day buffer incase of holidays/weekends 45 | end_date = composite_equity_curve.index[-1] + timedelta(days=5) 46 | benchmark_symbol = qb.Symbol(bechmark_security_id) 47 | history = qb.History(benchmark_symbol, start_date, end_date, Resolution.Daily) 48 | closes = history.loc[benchmark_symbol].close 49 | closes = closes.resample('D').mean().interpolate(method='linear') 50 | closes = closes.reindex(pd.DatetimeIndex(composite_equity_curve.index)) # Line up benchmark index with portfolio index 51 | benchmark_daily_returns = list(closes.pct_change().dropna().values) 52 | 53 | # Beta 54 | performance_statistics['Beta'] = Statistics.Beta(daily_returns, benchmark_daily_returns) 55 | 56 | # Alpha 57 | performance_statistics['Alpha'] = Statistics.Alpha(daily_returns, benchmark_daily_returns, 0) 58 | 59 | # Tracking Error 60 | performance_statistics['TrackingError'] = Statistics.TrackingError(daily_returns, benchmark_daily_returns, 365) 61 | 62 | # Information Ratio 63 | performance_statistics['InformationRatio'] = Statistics.InformationRatio(daily_returns, benchmark_daily_returns) 64 | 65 | # Sharpe 66 | performance_statistics['SharpeRatio'] = Statistics.SharpeRatio(daily_returns, 0) 67 | 68 | # Sortino 69 | performance_statistics['Sortino'] = Sortino.evaluate(composite_equity_curve) 70 | 71 | # Max Drawdown 72 | performance_statistics['MaxDrawdown'] = "{:.2%}".format(Drawdown.evaluate(composite_equity_curve)) 73 | 74 | # Treynor Ratio 75 | performance_statistics['TreynorRatio'] = Statistics.TreynorRatio(daily_returns, benchmark_daily_returns, 0) 76 | 77 | # PSR 78 | #benchmark_sharpe = Statistics.SharpeRatio(benchmark_daily_returns, 0) 79 | #performance_statistics['ProbabilisticSharpeRatio'] = Statistics.ProbabilisticSharpeRatio(daily_returns, benchmark_sharpe) 80 | 81 | # Observed Sharpe Ratio 82 | performance_statistics['ObservedSharpeRatio'] = Statistics.ObservedSharpeRatio(daily_returns) 83 | 84 | # Round the statistics for a nice display 85 | for key, value in performance_statistics.items(): 86 | if not isinstance(value, str): 87 | performance_statistics[key] = round(value, 4) 88 | 89 | return pd.DataFrame(pd.Series(performance_statistics, name='value')) 90 | -------------------------------------------------------------------------------- /AlphaStream/AlphaInsightsStreamClient.py: -------------------------------------------------------------------------------- 1 | from .AlphaStreamEventClient import AlphaStreamEventClient 2 | class AlphaInsightsStreamClient(AlphaStreamEventClient): 3 | """ Alpha Streams Insight Streaming Client inherits from AlphaStreamEventClient. 4 | This has been kept to maintain backward compatibility. """ 5 | pass 6 | 7 | -------------------------------------------------------------------------------- /AlphaStream/AlphaStreamClient.py: -------------------------------------------------------------------------------- 1 | from .AlphaStreamRestClient import AlphaStreamRestClient 2 | 3 | class AlphaStreamClient(AlphaStreamRestClient): 4 | """ Alpha Streams Rest Client is the REST executor and client. 5 | Alpha Stream Client class inherits in order to maintain backward compatibility """ 6 | pass -------------------------------------------------------------------------------- /AlphaStream/AlphaStreamEventClient.py: -------------------------------------------------------------------------------- 1 | import pika 2 | from json import loads 3 | from time import sleep, time 4 | 5 | from .Models import HeartbeatPackage 6 | from .Models import AlphaResultPackage 7 | 8 | 9 | class AlphaStreamEventClient(object): 10 | """Alpha Streams Streaming Client """ 11 | 12 | def __init__(self, user, password, ipaddress, virtualhost, exchange): 13 | self.__exchange = exchange 14 | 15 | # Create connection, pass Rabbit MQ credentials 16 | credentials = pika.PlainCredentials(user, password) 17 | parameters = pika.ConnectionParameters(ipaddress, 5672, virtualhost, credentials) 18 | 19 | # Declare queue and bind to exchange: 20 | self.__connection = pika.BlockingConnection(parameters) 21 | self.__channel = self.__connection.channel() 22 | 23 | def StreamSynchronously(self, alphaId, timeout=10): 24 | """ Stream a specific alpha id to a supplied callback method for timeout seconds. """ 25 | result = self.__channel.queue_declare(queue=alphaId, durable=False, exclusive=False, auto_delete=True, 26 | arguments={'x-message-ttl': 60000}) 27 | queue = self.__channel.queue_bind(exchange=self.__exchange, queue=alphaId, routing_key=alphaId) 28 | end = time() + timeout 29 | 30 | # Stream out queue for period. 31 | while time() < end: 32 | method, properties, body = self.__channel.basic_get(alphaId, auto_ack=True) 33 | if method: 34 | # Process the package container 35 | decoded = loads(body) 36 | if decoded['alpha-id'] != alphaId: 37 | continue 38 | 39 | etype = decoded['eType'] 40 | # Alpha results are either Insights or Orders 41 | if etype == 'AlphaResult': 42 | package = AlphaResultPackage(decoded) 43 | 44 | # Yield the insights 45 | for i in package.Insights: 46 | yield i 47 | 48 | # Yield the orders 49 | for order in package.Orders: 50 | yield order 51 | 52 | # Heartbeat is emitted once per minute to show connection is open 53 | elif etype == 'AlphaHeartbeat': 54 | yield HeartbeatPackage(decoded) 55 | 56 | else: 57 | raise Exception(f'Invalid type: {etype}') 58 | else: 59 | sleep(0.01) 60 | 61 | # Tidy up 62 | self.__channel.queue_unbind(queue=alphaId, exchange=self.__exchange, routing_key=alphaId) 63 | self.__channel.queue_delete(queue=alphaId, if_unused=True) 64 | self.__channel.close() -------------------------------------------------------------------------------- /AlphaStream/Models/Alpha.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from .Author import Author 3 | 4 | 5 | class Alpha(object): 6 | """Algorithm alpha model from the Alpha Streams marketplace.""" 7 | 8 | def __init__(self, json): 9 | 10 | self.Id = json['id'] 11 | 12 | # Unique hash identifier for this published Alpha family id. 13 | self.FamilyId = json['family-id'] 14 | 15 | self.Authors = [] 16 | authors = json.get('authors', None) 17 | if authors is not None: 18 | for a in json['authors']: 19 | self.Authors.append(Author(a)) 20 | 21 | # Assets classes traded in the Alpha: Equity, Forex, Crypto, CFDs, Options, Futures 22 | self.AssetClasses = json.get('asset-classes', None) 23 | 24 | # Alpha's Insight magnitude accuracy 25 | self.Accuracy = json.get('accuracy', None) 26 | 27 | # Number of backtests run on the alpha prior to submission 28 | self.AnalysesPerformed = json.get('analyses-performed', None) 29 | 30 | # Boolean - True if the author is trading this strategy else False 31 | self.AuthorTrading = json.get('author-trading', False) 32 | 33 | # Alpha description provided by the author 34 | self.Description = json.get('description', '') 35 | 36 | # Estimated depth of the Alpha in USD 37 | self.EstimatedDepth = json.get('estimated-depth', None) 38 | 39 | # Number of hours spent coding the project 40 | self.EstimatedEffort = json.get('estimated-effort', None) 41 | 42 | # Alpha name displayed in the marketplace 43 | self.Name = json.get('name', None) 44 | 45 | # 1 - Average correlation of the alpha with the rest of the market 46 | self.Uniqueness = json.get('uniqueness', None) 47 | 48 | # Live, rolling 90-day Sharpe ratio (annualized) 49 | self.SharpeRatio = json.get('sharpe-ratio', None) 50 | 51 | # Version of the alpha -- authors often submit multiple versions with various updates 52 | self.Version = json.get('version', None) 53 | 54 | # Alpha's running status - either "running" or "stopped" 55 | self.Status = json.get('status', None) 56 | 57 | # Number of Insights in the alpha backtest 58 | self.InSampleInsights = json.get('in-sample-insights', None) 59 | 60 | # Number of Insights in live trading 61 | self.LiveTradingInsights = json.get('live-trading-insights', None) 62 | 63 | # Number of Insights in the out-of-sample backtests run over the alpha's live period 64 | self.OutOfSampleInsights = json.get('out-of-sample-insights', None) 65 | 66 | # Tags assigned to the alpha by the author 67 | self.Tags = json.get('tags', []) 68 | 69 | # Number of parameters in the alpha 70 | self.Parameters = json.get('parameters', None) 71 | 72 | # Dynamic Time Warping distance between live and out-of-sample backtest returns 73 | self.OutOfSampleDtwDistance = json.get('out-of-sample-dtw-distance', None) 74 | 75 | # Returns correlation between live and out-of-sample backtest returns 76 | self.OutOfSampleReturnsCorrelation = json.get('out-of-sample-returns-correlation', None) 77 | 78 | # Alpha free-licensing trial period (days) 79 | self.Trial = json.get('trial', 0) 80 | 81 | # Alpha's capacity: the maximum funds that can be allocated to it 82 | self.Capacity = json.get('capacity', 0) 83 | 84 | # Alpha's allocated capacity: funds allocated so far 85 | self.CapacityAllocated = json.get('capacity-allocated', 0) 86 | 87 | # Alpha's reserve price 88 | self.ReservePrice = json.get('reserve-price', 0) 89 | 90 | def __repr__(self): 91 | return f''' 92 | Alpha Id: {self.Id} 93 | Name: {self.Name} 94 | Sharpe Ratio: {self.SharpeRatio} 95 | Uniqueness: {self.Uniqueness} 96 | Capacity: {self.Capacity} 97 | Capacity Allocated: {self.CapacityAllocated} 98 | Reserve Price: {self.ReservePrice} 99 | Status: {self.Status}''' -------------------------------------------------------------------------------- /AlphaStream/Models/AlphaResultPackage.py: -------------------------------------------------------------------------------- 1 | from .Order import Order 2 | from .Insight import Insight 3 | from .OrderEvent import OrderEvent 4 | 5 | class AlphaResultPackage: 6 | """Package holding a group of insights, orders, and/or order events from one moment of time.""" 7 | 8 | def __init__(self, json): 9 | 10 | self.AlphaId = json['alpha-id'] 11 | 12 | self.AlgorithmId = json['algorithm-id'] 13 | 14 | self.Insights = [] 15 | 16 | self.Orders = [] 17 | 18 | insights = json.get('insights', []) 19 | 20 | for i in insights: 21 | i['source'] = 'live trading' 22 | self.Insights.append(Insight(i)) 23 | 24 | orderEvents = [OrderEvent(x) for x in json.get('order-events', [])] 25 | orders = json.get('orders', []) 26 | for order in orders: 27 | order['source'] = 'live trading' 28 | ord = Order(order) 29 | 30 | if len(orderEvents) == 0: 31 | raise Exception(f'No OrderEvents were provided for order {ord.Id}') 32 | 33 | ord.OrderEvents = [x for x in orderEvents if x.Id.startswith(ord.Id)] 34 | self.Orders.append(ord) -------------------------------------------------------------------------------- /AlphaStream/Models/Author.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | class Author(object): 4 | """ Author object for storing user information """ 5 | 6 | def __init__(self, json): 7 | 8 | # Unique author ID hash 9 | self.Id = json['id'] 10 | 11 | # List of alphas IDs by the author 12 | self.Alphas = json.get('alphas', []) 13 | 14 | # Number of author's alphas listed on the market 15 | self.AlphasListed = json.get('alphas-listed', None) 16 | 17 | # Average number of hours the author spent coding on an alpha 18 | self.AnalysisAverageLength = json.get('analysis-average-length', None) 19 | 20 | # Total number of backtests performed by the author 21 | self.Backtests = json.get('backtests', None) 22 | 23 | # Biography provided by the author 24 | self.Biography = json.get('biography', None) 25 | 26 | # Number of forum discussions the author has participated in 27 | self.ForumDiscussions = json.get('forum-discussions', None) 28 | 29 | # Number of comments the author has posted in the community forum 30 | self.ForumComments = json.get('forum-comments', None) 31 | 32 | # Author's preferred coding language 33 | self.Language = json.get('language', None) 34 | 35 | # UTC time the author was last online 36 | self.LastOnlineTime = datetime.utcfromtimestamp(json['last-online-time']) if 'last-online-time' in json else None 37 | 38 | # Author's location - city, state, country 39 | self.Location = json.get('location', None) 40 | 41 | # Total number of projects the author has created 42 | self.Projects = json.get('projects', None) 43 | 44 | # UTC time the author signed up with QuantConnect 45 | self.SignUpTime = datetime.utcfromtimestamp(json['signup-time']) if 'signup-time' in json else None 46 | 47 | # Author's social media profile 48 | self.SocialMedia = json.get('social-media', None) 49 | 50 | def __repr__(self): 51 | return f'Alpha Stream Author {self.Id[:5]:>5} is from {self.Location}. Signed up {self.SignUpTime} and codes in {self.Language}' -------------------------------------------------------------------------------- /AlphaStream/Models/Bid.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | class Bid(object): 4 | """Information on a specific bid made to license an Alpha.""" 5 | 6 | def __init__(self, json): 7 | 8 | # Unique ID of the did 9 | self.Id = json['id'] 10 | 11 | # Expiration time of the bid. 12 | self.GoodUntil = datetime.utcfromtimestamp(json.get('good-until-time', 0)) 13 | 14 | # Allocation that the alpha will be licensed to 15 | self.Allocation = json.get('allocation', 0) 16 | 17 | # Period that the alpha will be licensed to (in days) 18 | self.LicensePeriod = json.get('license-period', 0) 19 | 20 | # The maximum bid price per 4-week period 21 | self.MaximumPrice = json.get('maximum-price', 0) 22 | 23 | 24 | def __repr__(self): 25 | return (f'Bid of ${self.MaximumPrice} for a ${self.Allocation} allocation to license ' 26 | + f'for the next {self.LicensePeriod} days is good until {self.GoodUntil}.') -------------------------------------------------------------------------------- /AlphaStream/Models/BidReponse.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | class BidReponse(object): 4 | """Result of a bid to license an Alpha.""" 5 | 6 | def __init__(self, json): 7 | 8 | # Boolean indicating success 9 | self.Success = json.get('success', False) 10 | 11 | # Capacity allocated if the bid is successful 12 | self.CapacityAllocated = json.get('capacity-allocated', 0) 13 | 14 | # True if the bid resulted in a new license 15 | self.Licensed = json.get('licensed', False) 16 | 17 | # True if the out bid 18 | self.Outbid = json.get('outbid', False) 19 | 20 | def __repr__(self): 21 | if self.Licensed: 22 | return f'Licensed for {self.CapacityAllocated}' 23 | if self.Outbid: 24 | return 'Outbid' 25 | return 'Not licenced nor outbid' if self.Success else 'Failed to place a bid' -------------------------------------------------------------------------------- /AlphaStream/Models/BidResult.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from .Bid import Bid 3 | 4 | class BidResult(object): 5 | """Result of a bid to license an Alpha.""" 6 | 7 | def __init__(self, json): 8 | 9 | # True if the bid is successful 10 | self.Success = json.get('success', None) 11 | 12 | # Alpha's Insight magnitude accuracy 13 | self.ActiveBid = json.get('active-bid', None) 14 | if self.ActiveBid: 15 | self.ActiveBid = Bid(self.ActiveBid) 16 | 17 | # Time that the next auction will occur 18 | self.NextAuctionTime = datetime.utcfromtimestamp(json.get('next-auction-time', 0)) 19 | 20 | # Alpha's capacity for the next auction 21 | self.NextAuctionCapacity = json.get('next-auction-capacity', 0) 22 | 23 | # Minimum capital required to place a bid 24 | self.MinimumCapitalRequired = json.get('minimum-capital-required', 0) 25 | 26 | def __repr__(self): 27 | if not self.Success: 28 | return 'Unsuccessful bid' 29 | return f'''{self.ActiveBid} 30 | Next auction time: {self.NextAuctionTime} 31 | Next auction capacity: {self.NextAuctionCapacity} 32 | Minimum capital required: {self.MinimumCapitalRequired}''' -------------------------------------------------------------------------------- /AlphaStream/Models/HeartbeatPackage.py: -------------------------------------------------------------------------------- 1 | class HeartbeatPackage: 2 | """Package holding a heartbeat emitted from one moment of time.""" 3 | 4 | def __init__(self, json): 5 | 6 | self.AlphaId = json.get('alpha-id') 7 | self.AlgorithmId = json.get('algorithm-id') 8 | self.MachineTime = json.get('machine-time') 9 | 10 | def __repr__(self): 11 | return f'AlphaId: {self.AlphaId[0:5]} AlgorithmId: {self.AlgorithmId[0:7]} Heartbeat: {self.MachineTime}' -------------------------------------------------------------------------------- /AlphaStream/Models/Insight.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | 4 | class Insight: 5 | """Individual prediction/insight generated by an Alpha in the QuantConnect Alpha Streams market""" 6 | 7 | def __init__(self, json): 8 | # Unique hash ID of the Insight 9 | self.Id = json['id'] 10 | 11 | # Insight type - Price or Volatility. Only price insights are supported at this time 12 | self.Type = json.get('type', None) 13 | 14 | # Predicted direction of movement - Up, Down, or Flat 15 | self.Direction = json.get('direction', None) 16 | 17 | # Double score of the direction prediction (0,1) 18 | self.DirectionScore = json.get('score-direction', None) 19 | 20 | # Duration of the Insight in seconds 21 | self.Period = json.get('period', None) 22 | 23 | # UTC time the Insight was created 24 | self.CreatedTime = datetime.utcfromtimestamp(json['created-time']) if 'created-time' in json else None 25 | 26 | # UTC time the Insight expired 27 | self.CloseTime = datetime.utcfromtimestamp(json['close-time']) if 'close-time' in json else None 28 | 29 | # Predicted magnitude change in Insight price or volatility (decimals) 30 | self.Magnitude = json.get('magnitude', None) 31 | 32 | # Double score of the magnitude prediction (0,1) 33 | self.MagnitudeScore = json.get('score-magnitude', None) 34 | 35 | # Author-set confidence that the Insight predicted duration, magnitude, and direction are correct 36 | self.Confidence = json.get('confidence', None) 37 | 38 | # Unique hash or author-set name of the model the Insight was created from 39 | self.SourceModel = json.get('source-model', None) 40 | 41 | # Insight group hash if the Insight was grouped with other Insights 42 | self.Group = json.get('group', None) 43 | 44 | # Where the Insight was generated - in sample, out of sample, or live trading 45 | self.Source = json.get('source', None) 46 | 47 | # Value of the security at the time the Insight was created 48 | self.ReferenceValue = json.get('reference-value', None) 49 | 50 | # Value of the security at the time the Insight expired 51 | self.ReferenceValueFinal = json.get('reference-value-final', None) 52 | 53 | # Estimated value of the Insight in USD 54 | self.EstimatedValue = json.get('estimated-value', None) 55 | 56 | # Unique QuantConnect identifier of the Insight security 57 | self.Symbol = json.get('symbol', None) 58 | 59 | # Ticker of the asset underlying the Insight at the time the insight was created 60 | self.Ticker = json.get('ticker', None) 61 | 62 | # Boolean - True if the Insight cannot be trusted (i.e. invalidated due to bug) else False 63 | self.Invalid = json.get('invalid', None) 64 | 65 | # Boolean - True if the Insight has expired and been scored 66 | self.ScoreFinal = json.get('score-final', False) 67 | 68 | # Decimal weight assigned to the Insight 69 | self.Weight = json.get('weight', None) 70 | 71 | def __repr__(self): 72 | return f'{self.CreatedTime} Alpha {self.Source} {self.Type} insight for {self.Ticker:<10} going {self.Direction} over the next {self.Period}s' -------------------------------------------------------------------------------- /AlphaStream/Models/OrderEnums.py: -------------------------------------------------------------------------------- 1 | import enum 2 | 3 | class OrderType(enum.Enum): 4 | 5 | # Market Order Type 6 | Market = 'market' 7 | 8 | # Limit Order Type 9 | Limit = 'limit' 10 | 11 | # Stop Market Order Type - Fill at market price when break target price 12 | StopMarket = 'stopMarket' 13 | 14 | # Stop limit order type - trigger fill once pass the stop price; but limit fill to limit price 15 | StopLimit = 'stopLimit' 16 | 17 | # Market on open type - executed on exchange open 18 | MarketOnOpen = 'marketOnOpen' 19 | 20 | # Market on close type - executed on exchange closed 21 | MarketOnClose = 'marketOnClose' 22 | 23 | # Option Exercise Order Type 24 | OptionExercise = 'optionExercise' 25 | 26 | class OrderDirection(enum.Enum): 27 | 28 | # Buy Order 29 | Buy = 'buy' 30 | 31 | # Sell Order 32 | Sell = 'sell' 33 | 34 | # Default Value - No Order Direction 35 | Hold = 'hold' 36 | 37 | 38 | class OrderStatus(enum.Enum): 39 | New = 'new' 40 | 41 | Submitted = 'submitted' 42 | 43 | PartiallyFilled = 'partiallyFilled' 44 | 45 | Filled = 'filled' 46 | 47 | Canceled = 'canceled' 48 | 49 | NoneOrder = "none" 50 | 51 | Invalid = 'invalid' 52 | 53 | CancelPending = 'cancelPending' 54 | 55 | UpdateSubmitted = 'updateSubmitted' -------------------------------------------------------------------------------- /AlphaStream/Models/OrderEvent.py: -------------------------------------------------------------------------------- 1 | from .OrderEnums import * 2 | from datetime import datetime 3 | 4 | 5 | class OrderEvent: 6 | def __init__(self, json): 7 | 8 | # Unique hash of the algorithm 9 | self.AlgorithmId = json.get('algorithm-id') 10 | 11 | # Unique hash of the source of the order that the order event is associated with 12 | self.OrderId = json.get('order-id') 13 | 14 | # Unique hash of the order event 15 | self.OrderEventId = json.get('order-event-id') 16 | 17 | # Unique hash of the source of the order event 18 | self.Id = f"{self.AlgorithmId}-{self.OrderId}-{self.OrderEventId}" 19 | 20 | # QuantConnect identifier for the order asset 21 | self.Symbol = json.get('symbol') 22 | 23 | # Unix time when the order event occurred 24 | self.Time = datetime.utcfromtimestamp(json.get('time')) 25 | 26 | # Fill-status of the order - new, submitted, partially filled, filled, canceled, none, invalid, cancel pending, update submitted 27 | self.Status = OrderStatus(json.get('status')) 28 | 29 | # Total fees for the order 30 | self.OrderFeeAmount = json.get('order-fee-amount') 31 | 32 | # Currency of the order fees 33 | self.OrderFeeCurrency = json.get('order-fee-currency') 34 | 35 | # Order fill price 36 | self.FillPrice = json.get('fill-price') 37 | 38 | # Currency of the order price 39 | self.FillPriceCurrency = json.get('fill-price-currency') 40 | 41 | # Number of shares filled 42 | self.FillQuantity = json.get('fill-quantity') 43 | 44 | # Direction of the order - buy, sell, hold 45 | self.Direction = OrderDirection(json.get('direction')) 46 | 47 | # Message attached to the order conveying additional information about the order event by the author 48 | self.Message = json.get('message', '') 49 | 50 | # Boolean if the order is an option assignment 51 | self.IsAssignment = json.get('is-assignment') 52 | 53 | # Number of shares of the order 54 | self.Quantity = json.get('quantity') 55 | 56 | # Stop price set for the order 57 | self.StopPrice = json.get('stop-price') 58 | 59 | # Limit price set for the order 60 | self.LimitPrice = json.get('limit-price') 61 | 62 | 63 | def __repr__(self, extended = True): 64 | 65 | if (extended): 66 | rep = f'Time: {self.Time} ID: {self.Id} Symbol: {self.Symbol} Status: {self.Status.name} Quantity: {self.Quantity}' 67 | else: 68 | rep = f'Time: {self.Time} OrderEventId: {self.OrderEventId} Status: {self.Status.name} Quantity: {self.Quantity}' 69 | 70 | if self.FillQuantity != 0: 71 | rep += f' Fill Quantity: {self.FillQuantity} Fill Price: {self.FillPrice} {self.FillPriceCurrency}' 72 | 73 | if self.LimitPrice is not None: 74 | rep += f' Limit Price: {self.LimitPrice}' 75 | 76 | if self.StopPrice is not None: 77 | rep += f' Stop Price: {self.StopPrice}' 78 | 79 | if self.OrderFeeAmount != 0: 80 | rep += f' Order Fee: {self.OrderFeeAmount} {self.OrderFeeCurrency}' 81 | 82 | if len(self.Message) > 0: 83 | rep += f' Message: "{self.Message}"' 84 | 85 | return rep -------------------------------------------------------------------------------- /AlphaStream/Models/Project.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from .Author import Author 3 | 4 | 5 | class Project: 6 | """Project object where the Alpha source resides. One Project can have multiple generated Alphas.""" 7 | 8 | def __init__(self, json): 9 | self.Author = Author(json['author']) if 'author' in json else None 10 | 11 | self.Name = json.get('name', None) 12 | 13 | self.CreatedTime = datetime.utcfromtimestamp(json['created-time']) if 'created-time' in json else None 14 | 15 | self.LastModifiedTime = datetime.utcfromtimestamp(json['last-modified-time']) if 'last-modified-time' in json else None -------------------------------------------------------------------------------- /AlphaStream/Models/RuntimeError.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | 4 | class RuntimeError: 5 | """Individual error set for an Alpha in the QuantConnect Alpha Streams market""" 6 | 7 | def __init__(self, json): 8 | self.Time = datetime.utcfromtimestamp(json['time']) if 'time' in json else None 9 | 10 | self.Error = json.get('error', None) 11 | 12 | self.Stacktrace = json.get('stacktrace', None) 13 | 14 | def __repr__(self): 15 | error = '' if self.Error is None else self.Error[:10] 16 | stacktrace = '' if self.Stacktrace is None else self.Stacktrace[:10] 17 | return f'Error at {self.Time}, message: {error}, stacktrace: {stacktrace}' -------------------------------------------------------------------------------- /AlphaStream/Models/Tag.py: -------------------------------------------------------------------------------- 1 | class Tag: 2 | """ Alpha tag and the number of alphas with the tag """ 3 | def __init__(self, result): 4 | self.TagName = result.get('tag', '') 5 | self.Matches = result.get('matches', 0) 6 | 7 | def __repr__(self): 8 | return f'"{self.TagName}" returned {self.Matches} matches' -------------------------------------------------------------------------------- /AlphaStream/Models/__init__.py: -------------------------------------------------------------------------------- 1 | from .Alpha import Alpha 2 | from .AlphaBacktestResult import AlphaBacktestResult 3 | from .Author import Author 4 | from .Bid import Bid 5 | from .BidReponse import BidReponse 6 | from .BidResult import BidResult 7 | from .HeartbeatPackage import HeartbeatPackage 8 | from .Insight import Insight 9 | from .AlphaResultPackage import AlphaResultPackage 10 | from .Project import Project 11 | from .RuntimeError import RuntimeError 12 | from .Symbol import Symbol 13 | from .Tag import Tag 14 | from .Order import * 15 | from .OrderEnums import * 16 | from .OrderEvent import * -------------------------------------------------------------------------------- /AlphaStream/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("QuantConnect.Algorithm.Python")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("QuantConnect.Algorithm.Python")] 12 | [assembly: AssemblyCopyright("Copyright © 2015")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("7007a02a-8d01-4a85-84e4-fcd58dc943e2")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /AlphaStream/QuantConnect/__init__.py: -------------------------------------------------------------------------------- 1 | # QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. 2 | # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | from hashlib import sha256 15 | from logging import exception 16 | from requests import Request, Session 17 | from time import time 18 | 19 | def create_secure_hash(timestamp, token): 20 | """Generate a secure hash for the authorization headers. 21 | Returns: 22 | Time based hash of user token and timestamp.""" 23 | hash_data = sha256() 24 | hash_data.update('{0}:{1}'.format(token, timestamp).encode('utf-8')) 25 | return hash_data.hexdigest() 26 | 27 | 28 | class ApiConnection: 29 | """API Connection and Hash Manager 30 | Attributes: 31 | client(str): Authorized client to use for requests. 32 | userId(int/str): User Id number from QuantConnect.com account. Found at www.quantconnect.com/account. 33 | token(str): Access token for the QuantConnect account. Found at www.quantconnect.com/account. 34 | """ 35 | def __init__(self, userId, token): 36 | self.client = 'https://www.quantconnect.com/api/v2/' 37 | self.userId = str(userId) 38 | self.token = token 39 | if len(self.userId) * len(self.token) == 0: 40 | exception('Cannot use empty string for userId or token. Found yours at www.quantconnect.com/account') 41 | 42 | 43 | def connected(self): 44 | """Return true if connected successfully.""" 45 | request = Request('GET', 'authenticate') 46 | result = self.try_request(request) 47 | return result['success'] 48 | 49 | def try_request(self, request): 50 | """Place a secure request and get back an object of type T. 51 | Args: 52 | request: Result object of the request 53 | Returns: 54 | result: request response 55 | """ 56 | timestamp = int(time()) 57 | hash = create_secure_hash(timestamp, self.token) 58 | request.auth = (self.userId, hash) 59 | request.headers.update({'Timestamp': str(timestamp)}) 60 | request.url = self.client + request.url 61 | 62 | try: 63 | session = Session() 64 | response = session.send(request.prepare()) 65 | session.close() 66 | return response.json() 67 | except: 68 | exception('Failed to make REST request to {0}'.format(request.url)) 69 | return { 'success': False } -------------------------------------------------------------------------------- /AlphaStream/README.rst: -------------------------------------------------------------------------------- 1 | QuantConnect Alpha Stream Interaction via API (python edition) 2 | ============================================================== 3 | 4 | What is it 5 | ---------- 6 | 7 | **quantconnect-alphastream** is a Python package providing interaction via API with `QuantConnect Alpha Streams `_. 8 | 9 | Installation Instructions 10 | ------------------------- 11 | - Setup a `GitHub `_ account 12 | - `Fork `_ the `repository `_ of the project 13 | - Clone your fork locally 14 | - `Installing from local src `_ in Development Mode, i.e. in such a way that the project appears to be installed, but yet is still editable from the src tree. 15 | 16 | >>> git clone https://github.com/username/AlphaStream.git 17 | >>> python AlphaStream/setup.py install 18 | 19 | Alternatively: 20 | 21 | >>> pip install git+https://github.com/username/AlphaStream.git 22 | 23 | 24 | Enter Python's interpreter and type the following commands: 25 | 26 | >>> from AlphaStream import AlphaStreamRestClient 27 | >>> client = AlphaStreamRestClient(your-client-id, your-token) 28 | >>> insights = client.GetAlphaInsights(alpha-id) 29 | >>> for insight in insights: 30 | >>> print(insight) 31 | 32 | For your user id and token, please visit your `Organization Alpha Management Dashboard `_. 33 | -------------------------------------------------------------------------------- /AlphaStream/Requests/AddInsightsStreamRequest.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class AddInsightsStreamRequest(object): 4 | """ Request streaming insights for this specific alpha. """ 5 | 6 | def __init__(self, alphaId): 7 | self.AlphaId = str(alphaId) 8 | self.Endpoint = "alpha/" + self.Id 9 | 10 | def GetPayload(self): 11 | payload = { 12 | "AlphaId" : self.AlphaId 13 | } 14 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/CreateBidPriceRequest.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | 3 | class CreateBidPriceRequest(object): 4 | """ Create a bid price request. """ 5 | def __init__(self, *args, **kwargs): 6 | '''Create a new instance of CreateBidPriceRequest 7 | Args: 8 | alphaId: Unique id hash of an Alpha published to the marketplace. 9 | exclusive: Bid for the exclusive price (optional if shared is defined). 10 | shared: Bid for the shared price (optional if exclusive is defined). 11 | good_until: Expiration time of the bid.''' 12 | kwargs = kwargs.get('kwargs', kwargs) 13 | self.Id = kwargs.get('alphaId') 14 | self.Endpoint = f'alpha/{self.Id}/prices/bids/create' 15 | self.Bid = kwargs.get('bid', 0) 16 | self.Allocation = self.GetPrice('allocation', kwargs) 17 | self.Period = kwargs.get('period', 0) 18 | 19 | good_until = kwargs.get('good_until', datetime.utcnow() + timedelta(seconds=3602)) 20 | self.GoodUntil = (good_until - datetime(1970, 1, 1)).total_seconds() 21 | 22 | 23 | def GetPrice(self, key, kwargs): 24 | value = kwargs.get(key, 0) 25 | if value == int(value): 26 | return int(value) 27 | raise Exception(f'Please bid the {key} in whole dollar amounts, without cents') 28 | 29 | 30 | def GetPayload(self): 31 | payload = { 'id': self.Id, 'good-until': self.GoodUntil } 32 | if self.Bid > 0: 33 | payload['bid'] = self.Bid 34 | if self.Allocation > 0: 35 | payload['allocation'] = self.Allocation 36 | if self.Period > 0: 37 | payload['period'] = self.Period 38 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaBidRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaBidRequest: 2 | """ Fetch Alpha's latest bid """ 3 | 4 | def __init__(self, alphaId): 5 | self.Id = alphaId 6 | self.Endpoint = f"alpha/{self.Id}/prices/bids/read" 7 | 8 | def GetPayload(self): 9 | return { "id": self.Id } 10 | -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaByIdRequest.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | class GetAlphaByIdRequest(object): 4 | """ Request a specific alpha with a matching Alpha Id """ 5 | 6 | def __init__(self, alphaId): 7 | self.Id = str(alphaId) 8 | self.Endpoint = "alpha/" + self.Id 9 | 10 | def GetPayload(self): 11 | payload = { 12 | "id" : self.Id 13 | } 14 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaEquityCurveRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaEquityCurveRequest: 2 | """ Fetch an entire alpha equity curve with 1 point for the close of each day. """ 3 | 4 | def __init__(self, alphaId, date_format = 'date'): 5 | self.Id = alphaId 6 | self.Format = 'json' 7 | self.DateFormat = date_format 8 | self.Endpoint = f'/alpha/{alphaId}/equity' 9 | 10 | def GetPayload(self): 11 | payload = { 12 | "format": self.Format, 13 | "date-format": self.DateFormat 14 | } 15 | return payload 16 | -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaErrorsRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaErrorsRequest: 2 | """ Fetch an alpha error history, starting from `start` for a maximum of 1000 values """ 3 | 4 | def __init__(self, alphaId, start=0): 5 | self.Id = alphaId 6 | self.Start = start 7 | self.Endpoint = "alpha/{}/errors".format(alphaId) 8 | 9 | def GetPayload(self): 10 | payload = { 11 | "id": self.Id, 12 | "start": self.Start 13 | } 14 | return payload 15 | -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaInsightsRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaInsightsRequest: 2 | """ Fetch an alpha insights in batches, starting from `start` for a maximum of 1000 insights """ 3 | 4 | def __init__(self, alphaId, start = 0): 5 | self.Id = alphaId 6 | self.Start = start 7 | self.Endpoint = "alpha/{}/insights".format(alphaId) 8 | 9 | def GetPayload(self): 10 | payload = { 11 | "id" : self.Id, 12 | "start" : self.Start 13 | } 14 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaListRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaListRequest(object): 2 | """ Listing all alpha ids so you can maintain a dictionary and detect programatically when a new alpha is added to the API. """ 3 | 4 | def __init__(self): 5 | self.Endpoint = "alpha/list" 6 | 7 | def GetPayload(self): 8 | return None -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaOrdersRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaOrdersRequest: 2 | """ Fetch an alpha's orders in batches, starting from `start` """ 3 | 4 | def __init__(self, alphaId, start=0): 5 | self.Id = alphaId 6 | self.Start = start 7 | self.Endpoint = "alpha/{}/orders".format(alphaId) 8 | 9 | def GetPayload(self): 10 | payload = { 11 | "id": self.Id, 12 | "start": self.Start 13 | } 14 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAlphaTagsRequest.py: -------------------------------------------------------------------------------- 1 | class GetAlphaTagsRequest(object): 2 | """ Fetch all alpha tags and the number of alphas tagged with each. Tags can be used in SearchAlphas() """ 3 | 4 | def __init__(self): 5 | self.Endpoint = "alpha/tags/read" 6 | 7 | def GetPayload(self): 8 | """ Construct search query data payload from the initialized properties """ 9 | payload = {} 10 | 11 | return payload -------------------------------------------------------------------------------- /AlphaStream/Requests/GetAuthorByIdRequest.py: -------------------------------------------------------------------------------- 1 | class GetAuthorByIdRequest(object): 2 | """ Request a specific author with a matching Author Id """ 3 | 4 | def __init__(self, authorId): 5 | self.Id = str(authorId) 6 | self.Endpoint = "alpha/author/" + self.Id 7 | 8 | def GetPayload(self): 9 | payload = { 10 | "id" : self.Id 11 | } 12 | return payload 13 | -------------------------------------------------------------------------------- /AlphaStream/Requests/RemoveAlphaBidRequest.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | 3 | class RemoveAlphaBidRequest(object): 4 | """ Request used to remove an bid for an alpha. """ 5 | def __init__(self, *args, **kwargs): 6 | '''Create a new instance of CreateBidPriceRequest 7 | Args: 8 | alphaId: Unique id hash of an Alpha published to the marketplace. 9 | bidId: Unique id of an Bid made to the Alpha.''' 10 | self.Id = kwargs.get('alphaId') 11 | self.BidId = kwargs.get('bidId') 12 | self.Endpoint = f'alpha/{self.Id}/prices/bids/delete' 13 | 14 | def GetPayload(self): 15 | return { 'id': self.Id, 'bid-id': self.BidId } -------------------------------------------------------------------------------- /AlphaStream/Requests/__init__.py: -------------------------------------------------------------------------------- 1 | from .AddInsightsStreamRequest import AddInsightsStreamRequest 2 | from .CreateBidPriceRequest import CreateBidPriceRequest 3 | from .GetAlphaBidRequest import GetAlphaBidRequest 4 | from .GetAlphaByIdRequest import GetAlphaByIdRequest 5 | from .GetAlphaErrorsRequest import GetAlphaErrorsRequest 6 | from .GetAlphaEquityCurveRequest import GetAlphaEquityCurveRequest 7 | from .GetAlphaInsightsRequest import GetAlphaInsightsRequest 8 | from .GetAlphaListRequest import GetAlphaListRequest 9 | from .GetAlphaTagsRequest import GetAlphaTagsRequest 10 | from .GetAlphaOrdersRequest import GetAlphaOrdersRequest 11 | from .GetAuthorByIdRequest import GetAuthorByIdRequest 12 | from .RemoveAlphaBidRequest import RemoveAlphaBidRequest 13 | from .SearchAlphasRequest import SearchAlphasRequest 14 | from .SearchAuthorsRequest import SearchAuthorsRequest -------------------------------------------------------------------------------- /AlphaStream/Single Alpha Analysis/Single Alpha Analysis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantConnect/AlphaStreams/107e4be4df39f811a60659297a13f266fb9c6277/AlphaStream/Single Alpha Analysis/Single Alpha Analysis.pdf -------------------------------------------------------------------------------- /AlphaStream/__init__.py: -------------------------------------------------------------------------------- 1 | from .__version__ import __title__, __description__, __url__, __version__ 2 | from .__version__ import __build__, __author__, __author_email__, __license__ 3 | from .__version__ import __copyright__ 4 | 5 | __package__ = __title__ 6 | 7 | from .AlphaStreamClient import AlphaStreamClient 8 | from .AlphaStreamRestClient import AlphaStreamRestClient 9 | from .AlphaStreamEventClient import AlphaStreamEventClient 10 | from .AlphaInsightsStreamClient import AlphaInsightsStreamClient 11 | -------------------------------------------------------------------------------- /AlphaStream/__version__.py: -------------------------------------------------------------------------------- 1 | __title__ = 'AlphaStream' 2 | __description__ = 'QuantConnect AlphaStream API' 3 | __url__ = 'https://www.quantconnect.com/alpha/docs/' 4 | __version__ = '0.9.0' 5 | __build__ = 0x00010 6 | __author__ = 'QuantConnect Team' 7 | __author_email__ = 'support@quantconnect.com' 8 | __license__ = 'Apache 2.0' 9 | __copyright__ = 'Copyright 2019 QuantConnect' 10 | -------------------------------------------------------------------------------- /AlphaStream/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /AlphaStream/app.py: -------------------------------------------------------------------------------- 1 | try: 2 | import AlphaStream 3 | except ImportError: 4 | import os, sys 5 | from os.path import dirname 6 | sys.path.append(dirname(dirname(__file__))) 7 | 8 | from AlphaStream import AlphaStreamRestClient 9 | from AlphaStream.Requests import GetAlphaByIdRequest 10 | 11 | # For your user id and token, please visit your Fund Management Dashboard: https://www.quantconnect.com/alpha/democlient#api-access-tokens 12 | clientId = "c7bd966e930c4b15b2ec13eb0d6170d9" 13 | token = "7030e89cfcc1948f4f93e91edd93d6f687c737844a6969d99d609a78f8d0a5c4091ef11f31c4c0e9cccacefe36ff4c2ad0e15525a85c65b0eafa34064cd11b1c" 14 | alphaId = "d0fc88b1e6354fe95eb83225a" 15 | 16 | # Create the Alpha Streams SDKs 17 | api = AlphaStreamRestClient(clientId, token) 18 | 19 | print(api.Execute(GetAlphaByIdRequest(alphaId))) 20 | -------------------------------------------------------------------------------- /AlphaStream/launch.bat: -------------------------------------------------------------------------------- 1 | 2 | IF EXIST "C:\Program Files\Anaconda3\Scripts\jupyter-notebook.exe" ( 3 | "C:\Program Files\Anaconda3\Scripts\jupyter-notebook.exe" 4 | ) ELSE IF EXIST "C:\ProgramData\Anaconda3\Scripts\jupyter-notebook.exe" ( 5 | "C:\ProgramData\Anaconda3\Scripts\jupyter-notebook.exe" 6 | ) -------------------------------------------------------------------------------- /AlphaStream/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## ![AlphaStream](https://cdn.quantconnect.com/web/i/alpha/alpha_header_rev0.png) Alpha Streams API Change Log 2 | 3 | ### Introduction ## 4 | 5 | The Alpha Streams API SDK is a helper package for searching and connecting to the QuantConnect Alpha Streams marketplace and consuming insights from live running Alphas. 6 | 7 | ---- 8 | 9 | ### API v0.5 - [Specification](QuantConnect.API.Specification/QuantConnect_Alpha_0.5_swagger.yaml) 10 | 11 | #### Features: 12 | - Added Historical alpha prices endpoint: `/alpha/{id}/prices`. 13 | - Added Live runtime errors track record: `/alpha/{id}/errors`. 14 | - Added `Insight.CloseTime` as short cut for start of insight + in-market period (excluding holidays, after hours). 15 | - Added `Alpha.Status` property. After 10 runtime errors Alphas automatically will be stopped and their status updated from `running` to `stopped`. 16 | - Added `Alpha.AuthorTrading` property to indicate if the Author is actively trading the same signal. 17 | - Added `Insight.Group` property: when insights are intended to be traded together they share a common group hash (e.g. pairs trading). 18 | - Added `Insight.SourceModel` property to support alpha models with multiple signals to be joined together. Source Model is the class name. 19 | 20 | #### Bug Fixes: 21 | - Fixed inconsistencies with naming time indexed properties. `CreatedTime`, `LastModifiedTime`. 22 | - Renamed `Alpha.ListedDate` -> `Alpha.ListedTime` 23 | - Renamed `Insight.Reference` to more specific `ReferenceValue` to path way for future insight types. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | QuantConnect Platform Service Agreement 2 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 3 | 4 | This code is provided only for use with the ALpha Streams Repository and is not available for other commercial use beyond this purpose. It may not be copied, modified or distributed. All intellectual property remains with QuantConnect Corporation. 5 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Demo/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Demo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("QuantConnect.AlphaStream.Demo")] 8 | [assembly: AssemblyProduct("QuantConnect.AlphaStream.Demo")] 9 | [assembly: AssemblyCulture("")] 10 | 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] 15 | 16 | // The following GUID is for the ID of the typelib if this project is exposed to COM 17 | [assembly: Guid("b5fbaf11-8966-45a7-82c4-7b36f3a4d138")] 18 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Demo/QuantConnect.AlphaStream.Demo.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | Exe 6 | QuantConnect.AlphaStream.Demo 7 | net6.0 8 | false 9 | false 10 | QuantConnect Alpha Streams API SDK - Demo Program 11 | 12 | 13 | bin\Debug\ 14 | 15 | 16 | bin\Release\ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | PreserveNewest 28 | 29 | 30 | PreserveNewest 31 | 32 | 33 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Demo/alpha-credentials.json: -------------------------------------------------------------------------------- 1 |  { 2 | // Default configuration file. Defaulted values are shown commented out 3 | "client-id": "", 4 | "api-token": "", 5 | "rabbitmq-address": "", 6 | //"rabbitmq-port": 5672, 7 | "rabbitmq-user": "", 8 | "rabbitmq-password": "", 9 | "rabbitmq-exchange": "", 10 | //"rabbitmq-virtualhost": "\"/\;", 11 | //"rabbitmq-auto-recovery-enabled": true, 12 | //"rabbitmq-timeout": 5000 13 | //"rabbitmq-consumer-tag": 14 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Demo/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha-credentials-path": "./alpha-credentials.json" 3 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/CreateBid.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | from datetime import datetime, timedelta 5 | 6 | sys.path.append('../') 7 | 8 | from AlphaStream import AlphaStreamClient 9 | 10 | class CreateBid(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 14 | 15 | def test_shared_bid(self): 16 | quotes = len(self.client.GetAlphaQuotePrices("d0fc88b1e6354fe95eb83225a")) 17 | bid = self.client.CreateBid(alphaId = 'd0fc88b1e6354fe95eb83225a', shared = 1, good_until = datetime.utcnow() + timedelta(seconds = 3610)) 18 | self.assertIsNotNone(bid) 19 | self.assertEqual(bid, 'Bid price was successfully created.') 20 | self.assertEqual(quotes + 1, len(self.client.GetAlphaQuotePrices("d0fc88b1e6354fe95eb83225a"))) 21 | 22 | def test_exclusive_bid(self): 23 | quotes = len(self.client.GetAlphaQuotePrices("d0fc88b1e6354fe95eb83225a")) 24 | bid = self.client.CreateBid(alphaId = "d0fc88b1e6354fe95eb83225a", exclusive = 1, good_until = datetime.utcnow() + timedelta(seconds = 3610)) 25 | self.assertIsNotNone(bid) 26 | self.assertEqual(bid, 'Bid price was successfully created.') 27 | self.assertEqual(quotes + 1, len(self.client.GetAlphaQuotePrices("d0fc88b1e6354fe95eb83225a"))) 28 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/CreateReadConversation.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | import numpy as np 5 | from datetime import datetime 6 | 7 | sys.path.append('../') 8 | 9 | from AlphaStream import AlphaStreamClient 10 | 11 | class CreateConversationRequest(unittest.TestCase): 12 | def setUp(self): 13 | config = test_config() 14 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 15 | self.sender = config['testing_client_institution_id'] 16 | 17 | def test_create_conversation(self): 18 | alphaId = '118d1cbc375709792ea4d823a' 19 | email = 'support@quantconnect.com' 20 | subject = "Alpha Conversation" 21 | message = "Hello World!" 22 | cc = "support@quantconnect.com" 23 | request = self.client.CreateConversation(alphaId = alphaId, email = email, subject = subject, message = message, 24 | cc=cc) 25 | self.assertIsNotNone(request) 26 | self.assertEqual(request, 'Conversation thread was successfully created.') 27 | 28 | readResponse = self.client.ReadConversation(alphaId = alphaId) 29 | self.assertGreater(len(readResponse), 0) 30 | for x in readResponse: 31 | self.assertEqual(x.From['id'], self.sender) 32 | self.assertEqual(x.From['type'], 'client') 33 | self.assertEqual(x.Message, "Hello World!") 34 | self.assertIsInstance(x.UtcTimeReceived, datetime) -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaById.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | 5 | sys.path.append('../') 6 | 7 | from AlphaStream import AlphaStreamClient 8 | 9 | class GetAlphaByID(unittest.TestCase): 10 | def setUp(self): 11 | config = test_config() 12 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 13 | 14 | def test_get_alpha_by_id(self): 15 | alphaId = "d0fc88b1e6354fe95eb83225a" 16 | response = self.client.GetAlphaById(alphaId=alphaId) 17 | self.assertIsNotNone(response) 18 | self.assertEqual(response.Id, alphaId) 19 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaEquityCurve.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | import pandas as pd 4 | from test_config import * 5 | 6 | sys.path.append('../') 7 | 8 | from AlphaStream import AlphaStreamClient 9 | 10 | class AlphaEquityCurveRequest(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 14 | 15 | def test_get_equity_curve(self): 16 | alphaId = "d0fc88b1e6354fe95eb83225a" 17 | response = self.client.GetAlphaEquityCurve(alphaId=alphaId) 18 | self.assertIsInstance(response, pd.DataFrame) 19 | self.assertFalse(response.empty) 20 | self.assertListEqual(list(response.columns), ['equity', 'sample']) 21 | self.assertEqual(response['equity'][0], 1e6) 22 | self.assertEqual(response['sample'][0], "in sample") 23 | self.assertEqual(sum(response['sample'] == "in sample"), 1300) 24 | self.assertGreaterEqual(sum(response['sample'] == "live trading"), 351) 25 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaErrors.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | from datetime import datetime 5 | 6 | sys.path.append('../') 7 | 8 | from AlphaStream import AlphaStreamClient 9 | 10 | class AlphaErrorRequest(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 14 | 15 | def test_price_request(self): 16 | response = self.client.GetAlphaErrors(alphaId = '5443d94e213604f4fefbab185') 17 | self.assertIsNotNone(response) 18 | self.assertGreater(len(response), 0) 19 | self.assertEqual(response[0].Time, datetime(2019, 2, 19, 6, 7, 41)) 20 | self.assertEqual(str(response[0]), 'Error at 2019-02-19 06:07:41, message: Algorithm., stacktrace: System.Exc') 21 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaInsights.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from itertools import groupby 4 | from datetime import datetime, timedelta 5 | 6 | from test_config import * 7 | 8 | sys.path.append('../') 9 | 10 | from AlphaStream import AlphaStreamClient 11 | 12 | 13 | class Insights(unittest.TestCase): 14 | def setUp(self): 15 | config = test_config() 16 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 17 | 18 | def test_get_insights(self): 19 | 20 | alphaId = "d0fc88b1e6354fe95eb83225a" 21 | start = 0 22 | insights = [] 23 | # Fetch all Insights in the Alpha's backtest 24 | while start < 500: 25 | insights += self.client.GetAlphaInsights(alphaId, start) 26 | start += 100 27 | 28 | self.assertEqual(len(insights), 500) 29 | 30 | # check that Insights are in chronological order 31 | for i in range(len(insights) - 1): 32 | for j in insights[i+1:]: 33 | self.assertLessEqual(insights[i].CreatedTime, j.CreatedTime) 34 | 35 | response_ids = [x.Id for x in insights] 36 | 37 | expected_in_sample_ids = read_test_data("InsightTestData.txt") 38 | # check that response not in-sample IDs == expected not in-sample IDs 39 | self.assertEqual(len(response_ids), len(expected_in_sample_ids)) 40 | self.assertListEqual(response_ids, expected_in_sample_ids) 41 | 42 | def test_start_outside_range(self): 43 | alphaId = "0cf6ab8427517bdec388eeb37" 44 | 45 | # Use try-except here because we are testing for success 46 | # There is no assetDoesNotRaiseException, so we just want to make sure it succeeds and throw an error if not 47 | try: 48 | i = 17596 49 | while True: 50 | response = self.client.GetAlphaInsights(alphaId, start=i) 51 | i += 100 52 | if len(response) < 100: 53 | break 54 | except Exception as err: 55 | print(f'Possible API error encountered. {err}') 56 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaList.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | 5 | sys.path.append('../') 6 | 7 | from AlphaStream import AlphaStreamClient 8 | 9 | class AlphaIDList(unittest.TestCase): 10 | def setUp(self): 11 | config = test_config() 12 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 13 | 14 | 15 | def test_get_alpha_list(self): 16 | response = self.client.GetAlphaList() 17 | self.assertIsNotNone(response) 18 | self.assertGreater(len(response), 250) 19 | for id in response: 20 | self.assertIsInstance(id, str) 21 | self.assertEqual(len(id), 25) 22 | 23 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaOrders.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from itertools import groupby 4 | from datetime import datetime, timedelta 5 | 6 | from test_config import * 7 | 8 | sys.path.append('../') 9 | from AlphaStream.Models.OrderEnums import * 10 | from AlphaStream import AlphaStreamClient 11 | 12 | 13 | class GetAlphaOrders(unittest.TestCase): 14 | def setUp(self): 15 | config = test_config() 16 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 17 | 18 | def test_GetAlphaOrders(self): 19 | start = 0 20 | orders = [] 21 | alphaId = "21a2a00a097117a84788c1434" 22 | while start < 1000: 23 | response = self.client.GetAlphaOrders(alphaId, start = start) 24 | orders += response 25 | start += 100 26 | self.assertGreater(len(orders), 0) 27 | for i in range(len(orders) - 2): 28 | for order in orders[i+1 : len(orders) - i - 1]: 29 | self.assertLessEqual(orders[i].CreatedTime, order.CreatedTime) 30 | 31 | order = orders[i] 32 | self.assertNotEqual(OrderStatus.NoneOrder, order.Status) 33 | self.assertNotEqual(0, len(order.Symbol)) 34 | self.assertNotEqual(0, len(order.AlgorithmId)) 35 | self.assertNotEqual(0, order.OrderId) 36 | self.assertNotEqual(0, order.SubmissionLastPrice) 37 | self.assertNotEqual(0, order.SubmissionAskPrice) 38 | self.assertNotEqual(0, order.SubmissionBidPrice) 39 | self.assertNotEqual(0, len(order.Source)) 40 | 41 | if all([order.Type == x for x in [OrderType.Market, OrderType.MarketOnOpen, OrderType.MarketOnClose]]) and (order.Status == OrderStatus.Filled): 42 | self.assertNotEqual(0, order.Price) 43 | 44 | if order.Status == OrderStatus.Filled: 45 | orderEvent = order.OrderEvents[-1] 46 | self.assertTrue(orderEvent.Status == OrderStatus.Filled) 47 | self.assertNotEqual(0, orderEvent.FillPrice) 48 | self.assertNotEqual(0, len(orderEvent.FillPriceCurrency)) 49 | 50 | elif order.Status == OrderStatus.Canceled: 51 | orderEvent = order.OrderEvents[-1] 52 | self.assertTrue(orderEvent.Status == OrderStatus.Canceled) 53 | 54 | if (order.Type == OrderType.Limit) or (order.Type == OrderType.StopLimit): 55 | self.assertFalse(any([x.LimitPrice == 0 for x in order.OrderEvents])) 56 | if (order.Type == OrderType.StopMarket) or (order.Type == OrderType.StopLimit): 57 | self.assertFalse(any([x.StopPrice == 0 for x in order.OrderEvents])) 58 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaPrices.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | 5 | sys.path.append('../') 6 | 7 | from AlphaStream import AlphaStreamClient 8 | from AlphaStream import * 9 | 10 | class AlphaPriceRequest(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 14 | 15 | def test_price_request(self): 16 | response = self.client.GetAlphaQuotePrices(alphaId = 'd0fc88b1e6354fe95eb83225a') 17 | self.assertIsNotNone(response) 18 | self.assertEqual(response[0].PriceType, 'ask') 19 | self.assertEqual(response[0].SharedPrice, 1) 20 | self.assertEqual(response[0].ExclusivePrice, None) 21 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/GetAlphaTags.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | 5 | sys.path.append('../') 6 | 7 | from AlphaStream import * 8 | 9 | class AlphaTagRequest(unittest.TestCase): 10 | def setUp(self): 11 | config = test_config() 12 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 13 | 14 | def test_GetAlphaTags(self): 15 | response = self.client.GetAlphaTags() 16 | self.assertIsInstance(response, list) 17 | self.assertGreaterEqual(len(response), 40) 18 | for x in response: 19 | self.assertGreater(len(x.TagName), 0) 20 | self.assertGreaterEqual(x.Matches, 0) 21 | 22 | def test_SearchAlphaTagsMatch(self): 23 | get_tags_response = self.client.GetAlphaTags() 24 | for tag in get_tags_response: 25 | hasData = True 26 | search_alphas_response = [] 27 | start = 0 28 | while hasData: 29 | response = self.client.SearchAlphas(includedTags = [f'{tag.TagName}'], start = start) 30 | search_alphas_response += response 31 | start += 100 32 | hasData = False if len(response) < 100 else True 33 | 34 | self.assertEqual(len(search_alphas_response), tag.Matches) 35 | for alpha in search_alphas_response: 36 | self.assertIn(tag.TagName, alpha.Tags) -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/StreamInsightsTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | from datetime import datetime, timedelta 5 | from AlphaStream.Models import HeartbeatPackage, Insight 6 | 7 | sys.path.append('../') 8 | 9 | from AlphaStream import * 10 | class StreamAlphaInsights(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | 14 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 15 | self.streamClient = AlphaInsightsStreamClient(config['rabbitmq_user'], config['rabbitmq_password'], config['rabbitmq_ipaddress'], config['rabbitmq_virtualhost'], config['rabbitmq_exchange']) 16 | 17 | # Setup conditions 18 | alphaID = "31ac5498164db7341b041a732" 19 | try: 20 | self.client.Subscribe(alphaId=alphaID) 21 | self.client.Unsubscribe(alphaId=alphaID) 22 | except: 23 | self.client.Unsubscribe(alphaId=alphaID) 24 | 25 | def test_StreamInsights(self): 26 | ## Emits 1 BTCUSD insight every minute 27 | alphaId = '31ac5498164db7341b041a732' 28 | received = [] 29 | self.client.Subscribe(alphaId) 30 | 31 | for response in self.streamClient.StreamSynchronously(alphaId, timeout = 60): 32 | received += [response] 33 | self.assertGreater(len(received), 0) 34 | 35 | for response in received: 36 | if isinstance(response, Insight): 37 | self.assertEqual(response.Direction, 'flat') 38 | self.assertEqual(response.Source, 'live trading') 39 | self.assertEqual(response.Period, 86400.0) 40 | self.assertEqual(response.Symbol, 'BTCUSD XJ') 41 | self.assertEqual(response.Type, 'price') 42 | self.assertEqual(response.SourceModel, 'e2687a6a-24dd-47aa-b8c5-fcab7a30c70d') 43 | self.assertEqual(response.Weight, 0.5) 44 | self.assertEqual(response.Confidence, 0.5) 45 | self.assertEqual(response.Magnitude, 0.5) 46 | self.assertLessEqual(response.CreatedTime, datetime.utcnow()) 47 | self.assertGreater(response.CloseTime, datetime.utcnow()) 48 | self.assertEqual(response.CreatedTime + timedelta(seconds = response.Period), response.CloseTime) 49 | 50 | elif isinstance(response, HeartbeatPackage): 51 | self.assertEqual(response.AlphaId, alphaId) 52 | self.assertLessEqual(datetime.strptime(response.MachineTime, "%Y-%m-%dT%H:%M:%S.%fz"), datetime.utcnow()) 53 | self.assertEqual(response.AlgorithmId, 'A-f338cce0ac051831979d58e38fb7cc03') 54 | 55 | self.client.Unsubscribe(alphaId) 56 | 57 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/StreamingOrderTests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | from datetime import datetime, timedelta 5 | from AlphaStream.Models import HeartbeatPackage, OrderEvent, Order 6 | 7 | sys.path.append('../') 8 | 9 | from AlphaStream import * 10 | class StreamAlphaOrderEvents(unittest.TestCase): 11 | def setUp(self): 12 | config = test_config() 13 | 14 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 15 | self.streamClient = AlphaStreamEventClient(config['rabbitmq_user'], config['rabbitmq_password'], config['rabbitmq_ipaddress'], config['rabbitmq_virtualhost'], config['rabbitmq_exchange']) 16 | 17 | # Setup conditions 18 | alphaID = "21a2a00a097117a84788c1434" 19 | try: 20 | self.client.Subscribe(alphaId=alphaID) 21 | self.client.Unsubscribe(alphaId=alphaID) 22 | except: 23 | self.client.Unsubscribe(alphaId=alphaID) 24 | 25 | def test_StreamOrderEvents(self): 26 | alphaId = '21a2a00a097117a84788c1434' 27 | received = [] 28 | self.client.Subscribe(alphaId) 29 | 30 | for response in self.streamClient.StreamSynchronously(alphaId, timeout = 60): 31 | received += [response] 32 | self.assertGreater(len(received), 0) 33 | 34 | for response in received: 35 | if isinstance(response, Order): 36 | self.assertEqual(response.AlgorithmId, 'A-4f4343d0fd8e5ad2cf61ce69c2854434') 37 | self.assertEqual(response.Symbol, 'BTCUSD XJ') 38 | self.assertEqual(response.Source, 'live trading') 39 | if response.StopPrice is not None: 40 | self.assertNotEqual(response.StopPrice, 0) 41 | if response.LimitPrice is not None: 42 | self.assertNotEqual(response.StopPrice, 0) 43 | for x in [response.SubmissionLastPrice, response.SubmissionBidPrice, response.SubmissionAskPrice]: 44 | self.assertNotEqual(x, 0) 45 | for x in response.OrderEvents: 46 | self.assertTrue(x.Id.startswith(response.Id, 0, len(response.Id))) 47 | 48 | elif isinstance(response, HeartbeatPackage): 49 | self.assertEqual(response.AlphaId, alphaId) 50 | self.assertLessEqual(datetime.strptime(response.MachineTime, "%Y-%m-%dT%H:%M:%S.%fz"), datetime.utcnow()) 51 | self.assertEqual(response.AlgorithmId, 'A-4f4343d0fd8e5ad2cf61ce69c2854434') -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/SubscribeUnsubscribe.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | from test_config import * 4 | 5 | sys.path.append('../') 6 | 7 | from AlphaStream import AlphaStreamClient 8 | 9 | class AlphaSubscribeUnsubscribe(unittest.TestCase): 10 | def setUp(self): 11 | config = test_config() 12 | self.client = AlphaStreamClient(config['testing_client_institution_id'], config['testing_client_token']) 13 | 14 | # Setup conditions 15 | alphaID = "d0fc88b1e6354fe95eb83225a" 16 | try: 17 | self.client.Subscribe(alphaId=alphaID) 18 | self.client.Unsubscribe(alphaId=alphaID) 19 | except: 20 | self.client.Unsubscribe(alphaId=alphaID) 21 | 22 | def test_alpha_subscribe_unsubscribe(self): 23 | alphaID = "d0fc88b1e6354fe95eb83225a" 24 | subscribeRequest = self.client.Subscribe(alphaId=alphaID) 25 | unsubscribeRequest = self.client.Unsubscribe(alphaId=alphaID) 26 | self.assertTrue(subscribeRequest) 27 | self.assertTrue(unsubscribeRequest) 28 | 29 | def test_alpha_double_subscribe(self): 30 | alphaID = "d0fc88b1e6354fe95eb83225a" 31 | self.client.Subscribe(alphaId = alphaID) 32 | self.assertRaises(Exception, self.client.Subscribe, alphaID) 33 | 34 | # Make sure to unsubscribe at the end 35 | self.client.Unsubscribe(alphaId=alphaID) 36 | 37 | def test_alpha_subscribe_subscribe_same_family(self): 38 | alphaID = "80bbae649ca2e4e328fe49c0f" 39 | same_family = "965559f6bd86a053e8042e1bf" 40 | 41 | first_subscribe_request = self.client.Subscribe(alphaId=alphaID) 42 | second_subscribe_request = self.client.Subscribe(alphaId=same_family) 43 | 44 | first_unsubscribe_request = self.client.Unsubscribe(alphaId=alphaID) 45 | second_unsubscribe_request = self.client.Unsubscribe(alphaId=same_family) 46 | 47 | self.assertTrue(first_subscribe_request) 48 | self.assertTrue(second_subscribe_request) 49 | self.assertEqual(first_subscribe_request, second_subscribe_request) 50 | 51 | self.assertTrue(first_unsubscribe_request) 52 | self.assertTrue(second_unsubscribe_request) 53 | self.assertEqual(first_unsubscribe_request, second_unsubscribe_request) 54 | 55 | 56 | def test_alpha_unsubscribe_not_subscribed(self): 57 | alphaID = "d0fc88b1e6354fe95eb83225a" 58 | self.assertRaises(Exception, self.client.Unsubscribe, alphaID) 59 | 60 | def test_alpha_subscribe_stopped_alpha(self): 61 | alphaId = "5443d94e213604f4fefbab185" 62 | self.assertRaises(Exception, self.client.Subscribe, alphaId) 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/SymbolTests.py: -------------------------------------------------------------------------------- 1 | # QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. 2 | # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | try: 15 | import AlphaStream 16 | except ImportError: 17 | import os, sys 18 | from os.path import abspath, dirname 19 | path = abspath(dirname(dirname(dirname(__file__)))) 20 | sys.path.append(path) 21 | 22 | import pytest 23 | from datetime import datetime 24 | from AlphaStream.Models import Symbol 25 | 26 | # noinspection PyPep8 27 | spot_price_securities_cases = ( 28 | ( 'security_id', 'ticker', 'security_type', 'market', 'date_arg'), 29 | [('SPY R735QTJ8XC9X', 'SPY', 'Equity', 'USA', [1998, 1, 2]), 30 | ('AAPL R735QTJ8XC9X', 'AAPL', 'Equity', 'USA', [1998, 1, 2]), 31 | ('EURUSD 5O', 'EURUSD', 'Forex', 'FXCM', None), 32 | ('USDJPY 8G', 'USDJPY', 'Forex', 'Oanda', None), 33 | ('WTICOUSD 8I', 'WTICOUSD', 'Cfd', 'Oanda', None), 34 | ('BTCUSD XJ', 'BTCUSD', 'Crypto', 'GDAX', None), 35 | ('ED XKDEAL18BYP5', 'ED', 'Future', 'USA', [2020, 12, 15]), 36 | ]) 37 | 38 | option_security_cases = ( 39 | ( 'security_id', 'ticker', 'security_type', 'market', 'date_arg', 'underlying_id', 'option_right', 'option_style', 'strike_price'), 40 | [('SPY 3033WWUF8MUH2|SPY R735QTJ8XC9X', 'SPY', 'Option', 'USA', [2015, 9, 18], 'SPY R735QTJ8XC9X', 'Put', 'European', 195.5)]) 41 | 42 | 43 | @pytest.mark.parametrize(*spot_price_securities_cases) 44 | def test_spot_price_securities(security_id, ticker, security_type, market, date_arg): 45 | symbol = Symbol(security_id) 46 | assert symbol.ID == security_id 47 | assert symbol.Symbol == ticker 48 | assert symbol.SecurityType == security_type 49 | assert symbol.Market == market 50 | if symbol.SecurityType == 'Equity': 51 | assert symbol.Date == datetime(*date_arg) 52 | 53 | @pytest.mark.parametrize(*option_security_cases) 54 | def test_option_securities(security_id, ticker, security_type, market, date_arg, underlying_id, 55 | option_right, option_style, strike_price): 56 | symbol = Symbol(security_id) 57 | assert symbol.ID == security_id 58 | assert symbol.Symbol == ticker 59 | assert symbol.SecurityType == security_type 60 | assert symbol.Market == market 61 | assert symbol.Date == datetime(*date_arg) 62 | assert symbol.Underlying == Symbol(underlying_id) 63 | assert symbol.OptionRight == option_right 64 | assert symbol.StrikePrice == strike_price 65 | assert symbol.OptionStyle == option_style 66 | 67 | 68 | def test_equal_symbols_are_equal(): 69 | assert Symbol('SPY R735QTJ8XC9X') == Symbol('SPY R735QTJ8XC9X') 70 | 71 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/TestData/AlphaAuthorTestData.txt: -------------------------------------------------------------------------------- 1 | 01b9bafcd1279d35a42d4c00f:Alpha Stream Author 3ff61 is from Virginia, US. Signed up 2017-09-06 12:49:20 and codes in Py 2 | 03cd7746623f09e029a22da43:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 3 | 0a79f20ecf746a47ba10b1ff3:Alpha Stream Author 791dd is from Virginia, US. Signed up 2018-06-20 21:13:39 and codes in Py 4 | 2d3db6308e0086b2dd28c0512:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 5 | 4011751a28f8bca9caa79076f:Alpha Stream Author 04f63 is from Virginia, US. Signed up 2015-06-24 21:12:40 and codes in Py 6 | 53f2d3f4f54f788e06507cef1:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 7 | 5443d94e213604f4fefbab185:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 8 | 57a852c665c3bc3edc1d0bc64:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 9 | 59c617b46d2ecebdafb790c52:Alpha Stream Author 47952 is from Virginia, US. Signed up 2017-09-03 10:25:48 and codes in C# 10 | 635ccc2ae85f96d18663976d2:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 11 | 72c963e97dcfd13a3641a82cb:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 12 | 7861961542d71370b3895d7a8:Alpha Stream Author 791dd is from Virginia, US. Signed up 2018-06-20 21:13:39 and codes in Py 13 | 7d4bb39d5acd861a71146b385:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 14 | 801e624c0fa4affa6da3f998d:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 15 | 829ccf1f00743d434f410d0b3:Alpha Stream Author db51e is from None. Signed up 2018-12-31 19:04:49 and codes in Py 16 | 8f05a7dcfdc5082f56ab641a6:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 17 | 98c3da56b16131ff2fc8a10b5:Alpha Stream Author 791dd is from Virginia, US. Signed up 2018-06-20 21:13:39 and codes in Py 18 | c2f5b6dd985ce8890cbc68f95:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 19 | c98a822257cf2087e37fddff9:Alpha Stream Author d9273 is from None. Signed up 2016-11-29 18:55:58 and codes in C# 20 | cf8f7311a8660e1794dea9f3a:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 21 | cf967a38cf3054c9622e3a2e2:Alpha Stream Author 1ba2f is from Virginia, US. Signed up 2017-11-27 23:35:08 and codes in Py 22 | d0fc88b1e6354fe95eb83225a:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 23 | d990baf2c43392306c9ce0dbd:Alpha Stream Author 385cf is from Virginia, US. Signed up 2015-12-13 05:43:51 and codes in Py 24 | d9a666f710152132129bb1c8c:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 25 | e27b538ced15fc32c747bac8b:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 26 | ed4462e970ca16986ccff40dd:Alpha Stream Author 13594 is from Virginia, US. Signed up 2014-05-14 16:28:43 and codes in Py 27 | f12d74bf0684154cfc5ef0fd5:Alpha Stream Author 37446 is from Virginia, US. Signed up 2018-08-11 20:32:47 and codes in Py 28 | f26d1f503b79ee65607d887b8:Alpha Stream Author ac037 is from Virginia, US. Signed up 2016-04-06 19:13:57 and codes in Py 29 | f87437943664034416bd367f6:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 30 | fba24be20a7d21db14118e579:Alpha Stream Author 791dd is from Virginia, US. Signed up 2018-06-20 21:13:39 and codes in Py 31 | fdff7e753b54105b67210d743:Alpha Stream Author 2b255 is from Virginia, US. Signed up 2016-09-28 17:20:14 and codes in C# 32 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "testing_client_institution_id": "", 3 | "testing_client_token": "", 4 | "production_client_institution_id": "", 5 | "production_client_token": "", 6 | "rabbitmq_user": "", 7 | "rabbitmq_password": "", 8 | "rabbitmq_ipaddress": "", 9 | "rabbitmq_virtualhost": "", 10 | "rabbitmq_exchange": "" 11 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/runAllUnitTests.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | cwd = os.getcwd() 4 | files = [file for file in os.listdir(cwd) 5 | if file.endswith(".py") and not (file.startswith("runAll") or file.startswith('test_config'))] 6 | for file in files: 7 | print(f'Running {file}') 8 | os.system(f"python -m unittest discover -p \"*{file}\"") -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Python.Tests/test_config.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def test_config(): 5 | config_path = "config.json" 6 | 7 | with open(config_path) as f: 8 | config = json.load(f) 9 | 10 | return config 11 | 12 | 13 | def read_test_data(file_name): 14 | with open("TestData/" + file_name, "r") as f: 15 | text = f.read() 16 | text = text.strip("\n") 17 | return text.split("\n") 18 | 19 | 20 | def get_string_list(list_objects): 21 | result = [] 22 | for obj in list_objects: 23 | result.append(str(obj)) 24 | return result 25 | 26 | 27 | def save_test_data(file_name, list_objects): 28 | with open("TestData/" + file_name, "w") as f: 29 | for obj in list_objects: 30 | f.write(str(obj) + "\n") 31 | return 32 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/AlphaCredentialsTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace QuantConnect.AlphaStream.Tests 4 | { 5 | [TestFixture] 6 | public class AlphaCredentialsTests 7 | { 8 | [Test] 9 | public void CreatesSecureHash() 10 | { 11 | const long stamp = 1234567890L; 12 | var credentials = new AlphaCredentials("client-id", "api-token"); 13 | var hash = credentials.CreateSecureHash(stamp); 14 | Assert.AreEqual("c2f75992e7ada8e6c985b830ed5ce12065c1f7ebd0a84feac6447b9cce185f0b", hash); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/AlphaStreamClientTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using NUnit.Framework; 5 | using QuantConnect.Algorithm.Framework.Alphas; 6 | using QuantConnect.AlphaStream.Models; 7 | using QuantConnect.AlphaStream.Requests; 8 | using QuantConnect.Orders; 9 | 10 | namespace QuantConnect.AlphaStream.Tests 11 | { 12 | [TestFixture] 13 | public class AlphaStreamClientTests 14 | { 15 | [Test] 16 | public void StreamTest() 17 | { 18 | const string testAlphaId = "79e963f0f1160ff5789450b09"; 19 | 20 | // set credentials for connecting to your alpha streams exchange 21 | var info = new AlphaStreamCredentials( 22 | "35.231.13.1", 23 | 5672, 24 | "quantconnect_test", 25 | "", 26 | "QCAlphaExchange_quantconnect_test", 27 | "quantconnect_test" 28 | ); 29 | 30 | var client = new AlphaStreamEventClient(info); 31 | client.Connect(); 32 | 33 | client.InsightReceived += (sender, args) => 34 | { 35 | Assert.AreEqual(args.Insight.Direction, InsightDirection.Flat); 36 | Assert.AreEqual(args.Insight.Source, Source.LiveTrading); 37 | Assert.AreEqual(args.Insight.Period, Time.OneMinute); 38 | Assert.AreEqual(args.Insight.Symbol.ID.ToString(), "EURUSD 8G"); 39 | Assert.AreEqual(args.Insight.Type, InsightType.Price); 40 | Assert.AreEqual(args.Insight.SourceModel, "eef0aede-d827-454c-ab61-c3e410cdd449"); 41 | Assert.IsNull(args.Insight.Weight); 42 | Assert.IsNull(args.Insight.Confidence); 43 | Assert.IsNull(args.Insight.Magnitude); 44 | Assert.LessOrEqual(args.Insight.GeneratedTimeUtc, DateTime.UtcNow); 45 | Assert.Greater(args.Insight.CloseTimeUtc, DateTime.UtcNow); 46 | Assert.AreEqual(args.Insight.GeneratedTimeUtc.Add(args.Insight.Period), args.Insight.CloseTimeUtc); 47 | }; 48 | 49 | client.HeartbeatReceived += (sender, args) => 50 | { 51 | Assert.LessOrEqual(args.MachineTime, DateTime.UtcNow); 52 | Assert.AreEqual(args.AlphaId, testAlphaId); 53 | Assert.AreEqual(args.AlgorithmId, "A-a0b454181d0ec497d2989453a79b16c9"); 54 | }; 55 | 56 | client.OrderReceived += (sender, args) => 57 | { 58 | Assert.AreNotEqual(args.Order.Direction, OrderDirection.Hold); 59 | Assert.AreEqual(args.Order.Source, Source.LiveTrading); 60 | Assert.AreEqual(args.Order.AlgorithmId, "A-a0b454181d0ec497d2989453a79b16c9"); 61 | Assert.AreEqual(args.Order.Symbol, "EURUSD 8G"); 62 | var events = args.Order.OrderEvents; 63 | Assert.GreaterOrEqual(events.Count, 0); 64 | Assert.AreEqual(events.First().Symbol, "EURUSD 8G"); 65 | }; 66 | 67 | client.AddAlphaStream(new AddAlphaStreamRequest { AlphaId = testAlphaId }); 68 | 69 | Thread.Sleep(60000); 70 | client.Dispose(); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Credentials.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Newtonsoft.Json.Linq; 4 | using NUnit.Framework; 5 | 6 | namespace QuantConnect.AlphaStream.Tests 7 | { 8 | public static class Credentials 9 | { 10 | public static AlphaCredentials Test => LazyTestCredentials.Value; 11 | 12 | private static readonly Lazy LazyTestCredentials = new Lazy(() => 13 | { 14 | var directory = TestContext.CurrentContext.TestDirectory; 15 | var path1 = Path.Combine(directory, "config.json"); 16 | var contents = File.ReadAllText(path1); 17 | var config = JObject.Parse(contents); 18 | var credentialsPath = config["alpha-credentials-path"].Value(); 19 | var path = Path.Combine(directory, credentialsPath); 20 | return AlphaCredentials.FromFile(path); 21 | }); 22 | } 23 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Infrastructure/DoubleUnixSecondsDateTimeJsonConverterTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using NUnit.Framework; 4 | using QuantConnect.AlphaStream.Infrastructure; 5 | using QuantConnect.Util; 6 | 7 | namespace QuantConnect.AlphaStream.Tests.Infrastructure 8 | { 9 | [TestFixture] 10 | public class DoubleUnixSecondsDateTimeJsonConverterTests 11 | { 12 | private static readonly double DefaultDateTimeInDoubleUnixSeconds = default(DateTime).ToUnixTime(); 13 | 14 | private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings 15 | { 16 | Converters = { new DoubleUnixSecondsDateTimeJsonConverter() } 17 | }; 18 | 19 | [Test] 20 | public void RoundTripsDateTimeAsDoubleSeconds() 21 | { 22 | var y2k = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(122.99991); 23 | var target = new TargetType 24 | { 25 | DateTime = y2k, 26 | NullableDateTime = y2k 27 | }; 28 | var json = JsonConvert.SerializeObject(target, SerializerSettings); 29 | 30 | Assert.AreEqual("{\"DateTime\":946684800.12299991,\"NullableDateTime\":946684800.12299991}", json); 31 | 32 | var deserialized = JsonConvert.DeserializeObject(json, SerializerSettings); 33 | Assert.AreEqual(target.DateTime, deserialized.DateTime); 34 | Assert.AreEqual(target.NullableDateTime, deserialized.NullableDateTime); 35 | } 36 | 37 | [Test] 38 | public void RoundTripsDefaultValues() 39 | { 40 | var y2k = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(122.99991); 41 | var target = new TargetType 42 | { 43 | DateTime = default(DateTime), 44 | NullableDateTime = default(DateTime?) 45 | }; 46 | var json = JsonConvert.SerializeObject(target, SerializerSettings); 47 | 48 | // without specifying ignore default values, will serialize default(DateTime) just as any other date time value 49 | Assert.AreEqual($"{{\"DateTime\":{DefaultDateTimeInDoubleUnixSeconds:.0},\"NullableDateTime\":null}}", json); 50 | 51 | var deserialized = JsonConvert.DeserializeObject(json, SerializerSettings); 52 | Assert.AreEqual(target.DateTime, deserialized.DateTime); 53 | Assert.AreEqual(target.NullableDateTime, deserialized.NullableDateTime); 54 | } 55 | 56 | class TargetType 57 | { 58 | public DateTime DateTime { get; set; } 59 | public DateTime? NullableDateTime { get; set; } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Infrastructure/HyphenSeparatedComplexQueryParameterNamingConventionTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Runtime.Serialization; 3 | using Newtonsoft.Json; 4 | using NUnit.Framework; 5 | using QuantConnect.AlphaStream.Infrastructure; 6 | 7 | namespace QuantConnect.AlphaStream.Tests.Infrastructure 8 | { 9 | [TestFixture] 10 | public class HyphenSeparatedComplexQueryParameterNamingConventionTests 11 | { 12 | [Test] 13 | public void HandlesComplexNestedTypes() 14 | { 15 | var value = new Request 16 | { 17 | Outter = new Outter 18 | { 19 | Middle = new Middle 20 | { 21 | Inner = new Inner 22 | { 23 | Value = "my-value" 24 | } 25 | } 26 | } 27 | }; 28 | 29 | var convention = new HyphenSeparatedQueryParameterNamingConvention(); 30 | 31 | var member = typeof(Request).GetProperty(nameof(Request.Outter)); 32 | var parameters = convention.GetQueryNameValuePairs(member, value.Outter).ToList(); 33 | Assert.AreEqual(1, parameters.Count); 34 | Assert.AreEqual("outter-name-middle-name-inner-name-Value", parameters[0].Name); 35 | Assert.AreEqual(value.Outter.Middle.Inner.Value, parameters[0].Value); 36 | Assert.AreEqual(typeof(Inner).GetProperty(nameof(Inner.Value)), parameters[0].Member); 37 | } 38 | 39 | private class Request 40 | { 41 | // extra attributes test/document order of precedence when resolving the parameter name 42 | [QueryParameter("outter-name")] 43 | [JsonProperty("wrong-outter-name")] 44 | [DataMember(Name = "wrong-outter-name")] 45 | public Outter Outter { get; set; } 46 | } 47 | 48 | private class Outter 49 | { 50 | [JsonProperty("middle-name")] 51 | [DataMember(Name = "wrong-middle-name")] 52 | public Middle Middle { get; set; } 53 | } 54 | 55 | private class Middle 56 | { 57 | [DataMember(Name = "inner-name")] 58 | public Inner Inner { get; set; } 59 | } 60 | 61 | private class Inner 62 | { 63 | public string Value { get; set; } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Infrastructure/TimeTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using QuantConnect.AlphaStream.Infrastructure; 4 | 5 | namespace QuantConnect.AlphaStream.Tests.Infrastructure 6 | { 7 | [TestFixture] 8 | public class TimeTests 9 | { 10 | [Test] 11 | public void CreatesCorrectUnixTimeStamp() 12 | { 13 | var now = new DateTime(2000, 01, 01); 14 | var stamp = now.ToUnixTime(); 15 | Assert.AreEqual(946684800, stamp); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("QuantConnect.AlphaStream.Tests")] 8 | [assembly: AssemblyProduct("QuantConnect.AlphaStream.Tests")] 9 | [assembly: AssemblyCulture("")] 10 | 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] 15 | 16 | // The following GUID is for the ID of the typelib if this project is exposed to COM 17 | [assembly: Guid("042957ca-bda8-4e02-8456-0b1258621afa")] -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/QuantConnect.AlphaStream.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | Library 6 | net6.0 7 | QuantConnect.AlphaStream.Tests 8 | preview 9 | false 10 | false 11 | QuantConnect Alpha Streams API SDK - Tests 12 | 13 | 14 | bin\Debug\ 15 | 16 | 17 | bin\Release\ 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | all 28 | runtime; build; native; contentfiles; analyzers; buildtransitive 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | PreserveNewest 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/Setup.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using NUnit.Framework; 3 | 4 | namespace QuantConnect.AlphaStream.Tests 5 | { 6 | [SetUpFixture] 7 | public class Setup 8 | { 9 | [OneTimeSetUp] 10 | public void Tracing() 11 | { 12 | // turn request/response tracing 13 | AlphaStreamRestClient.RequestTracingEnabled = true; 14 | AlphaStreamRestClient.ResponseTracingEnabled = true; 15 | 16 | // route trace messages to console 17 | Trace.Listeners.Add(new ConsoleTraceListener()); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/alpha-credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | // Default configuration file. Defaulted values are shown commented out 3 | "client-id": "", 4 | "api-token": "", 5 | "rabbitmq-address": "", 6 | "rabbitmq-port": 5672, 7 | "rabbitmq-user": "", 8 | "rabbitmq-password": "", 9 | "rabbitmq-exchange": "", 10 | "rabbitmq-virtualhost": "" 11 | //"rabbitmq-auto-recovery-enabled": true, 12 | //"rabbitmq-timeout": 5000 13 | //"rabbitmq-consumer-tag": 14 | } 15 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.Tests/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha-credentials-path": "./alpha-credentials.json" 3 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantConnect.AlphaStream", "QuantConnect.AlphaStream\QuantConnect.AlphaStream.csproj", "{1C4A3A40-B5C9-4EB5-8776-C81AC10348E1}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantConnect.AlphaStream.Tests", "QuantConnect.AlphaStream.Tests\QuantConnect.AlphaStream.Tests.csproj", "{042957CA-BDA8-4E02-8456-0B1258621AFA}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuantConnect.AlphaStream.Demo", "QuantConnect.AlphaStream.Demo\QuantConnect.AlphaStream.Demo.csproj", "{B5FBAF11-8966-45A7-82C4-7B36F3A4D138}" 11 | EndProject 12 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "QuantConnect.AlphaStream.Python", "AlphaStream\QuantConnect.AlphaStream.Python.pyproj", "{4A5DED1F-3E34-40E2-B1F2-9A8A02195508}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8374AA55-6087-4598-8637-11226D53E1ED}" 15 | ProjectSection(SolutionItems) = preProject 16 | app.py = app.py 17 | EndProjectSection 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuantConnect", "..\Lean\Common\QuantConnect.csproj", "{EA634AA0-3DDF-4787-8A2D-309EB7F28980}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Any CPU = Debug|Any CPU 24 | Release|Any CPU = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {1C4A3A40-B5C9-4EB5-8776-C81AC10348E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {1C4A3A40-B5C9-4EB5-8776-C81AC10348E1}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {1C4A3A40-B5C9-4EB5-8776-C81AC10348E1}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {1C4A3A40-B5C9-4EB5-8776-C81AC10348E1}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {042957CA-BDA8-4E02-8456-0B1258621AFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {042957CA-BDA8-4E02-8456-0B1258621AFA}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {042957CA-BDA8-4E02-8456-0B1258621AFA}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {042957CA-BDA8-4E02-8456-0B1258621AFA}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {B5FBAF11-8966-45A7-82C4-7B36F3A4D138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {B5FBAF11-8966-45A7-82C4-7B36F3A4D138}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {B5FBAF11-8966-45A7-82C4-7B36F3A4D138}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {B5FBAF11-8966-45A7-82C4-7B36F3A4D138}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {4A5DED1F-3E34-40E2-B1F2-9A8A02195508}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {4A5DED1F-3E34-40E2-B1F2-9A8A02195508}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {EA634AA0-3DDF-4787-8A2D-309EB7F28980}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {EA634AA0-3DDF-4787-8A2D-309EB7F28980}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {EA634AA0-3DDF-4787-8A2D-309EB7F28980}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {EA634AA0-3DDF-4787-8A2D-309EB7F28980}.Release|Any CPU.Build.0 = Release|Any CPU 45 | EndGlobalSection 46 | GlobalSection(SolutionProperties) = preSolution 47 | HideSolutionNode = FALSE 48 | EndGlobalSection 49 | GlobalSection(ExtensibilityGlobals) = postSolution 50 | SolutionGuid = {4AADD43A-3198-48AB-828D-11DB5E5F693F} 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/AlphaCredentials.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Linq; 7 | 8 | namespace QuantConnect.AlphaStream 9 | { 10 | public class AlphaCredentials 11 | { 12 | [JsonProperty("client-id")] 13 | public string ClientId { get; } 14 | 15 | [JsonProperty("api-token")] 16 | public string ApiToken { get; } 17 | 18 | public AlphaCredentials(string clientId, string apiToken) 19 | { 20 | ClientId = clientId; 21 | ApiToken = apiToken; 22 | } 23 | 24 | public string CreateSecureHash(long stamp) 25 | { 26 | return ToSHA256($"{ApiToken}:{stamp}"); 27 | } 28 | 29 | public static AlphaCredentials FromConfiguration() 30 | { 31 | if (!File.Exists("config.json")) 32 | { 33 | throw new FileNotFoundException("Please specify 'alpha-credentials-path' in 'config.json'"); 34 | } 35 | 36 | var config = JObject.Parse(File.ReadAllText("config.json")); 37 | var credentialsPath = config["alpha-credentials-path"]; 38 | if (credentialsPath == null) 39 | { 40 | throw new Exception("Please specify 'alpha-credentials-path' in 'config.json'"); 41 | } 42 | 43 | return FromFile(credentialsPath.Value()); 44 | } 45 | 46 | public static AlphaCredentials FromFile(string path) 47 | { 48 | if (!File.Exists(path)) 49 | { 50 | throw new FileNotFoundException($"AlphaCredentials file not found: {new FileInfo(path).FullName}"); 51 | } 52 | 53 | return JsonConvert.DeserializeObject(File.ReadAllText(path)); 54 | } 55 | 56 | private static string ToSHA256(string data) 57 | { 58 | var crypt = new SHA256Managed(); 59 | var hash = new StringBuilder(); 60 | var crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(data), 0, Encoding.UTF8.GetByteCount(data)); 61 | foreach (var theByte in crypto) 62 | { 63 | hash.Append(theByte.ToString("x2")); 64 | } 65 | return hash.ToString(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/AlphaInsightsStreamClient.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Requests; 2 | 3 | namespace QuantConnect.AlphaStream 4 | { 5 | /// 6 | /// Client used to stream live alpha insights. 7 | /// 8 | /// Kept for backwards compatibility 9 | public class AlphaInsightsStreamClient : AlphaStreamEventClient, IAlphaInsightsStreamClient 10 | { 11 | public AlphaInsightsStreamClient(AlphaStreamCredentials credentials) : base(credentials) 12 | { 13 | } 14 | 15 | public bool AddAlphaStream(AddInsightsStreamRequest request) 16 | { 17 | return AddAlphaStream(request as AddAlphaStreamRequest); 18 | } 19 | 20 | public bool RemoveAlphaStream(RemoveInsightsStreamRequest request) 21 | { 22 | return RemoveAlphaStream(request as RemoveAlphaStreamRequest); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/AlphaInsightsStreamCredentials.cs: -------------------------------------------------------------------------------- 1 | namespace QuantConnect.AlphaStream 2 | { 3 | /// 4 | /// Defines the required connection information for connection to alpha streams streaming server 5 | /// 6 | /// Kept for backwards compatibility 7 | public class AlphaInsightsStreamCredentials : AlphaStreamCredentials 8 | { 9 | public AlphaInsightsStreamCredentials(string hostName, 10 | int port, 11 | string username, 12 | string password, 13 | string exchangeName, 14 | string virtualHost = "/", 15 | bool automaticRecoveryEnabled = true, 16 | int requestedConnectionTimeout = 5000, 17 | string consumerTag = null) 18 | : base(hostName, port, username, password, exchangeName, virtualHost, automaticRecoveryEnabled, requestedConnectionTimeout, consumerTag) 19 | { 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/AlphaStreamCredentials.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.IO; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace QuantConnect.AlphaStream 8 | { 9 | /// 10 | /// Defines the required connection information for connection to alpha streams streaming server 11 | /// 12 | public class AlphaStreamCredentials 13 | { 14 | [JsonProperty("rabbitmq-address")] 15 | public string HostName { get; set; } 16 | 17 | [JsonProperty("rabbitmq-port")] 18 | public int Port { get; set; } = 5672; 19 | 20 | [JsonProperty("rabbitmq-user")] 21 | public string Username { get; set; } 22 | 23 | [JsonProperty("rabbitmq-password")] 24 | public string Password { get; set; } 25 | 26 | [JsonProperty("rabbitmq-exchange")] 27 | public string ExchangeName { get; set; } 28 | 29 | [JsonProperty("rabbitmq-virtualhost")] 30 | public string VirtualHost { get; set; } = "/"; 31 | 32 | [JsonProperty("rabbitmq-auto-recovery-enabled"), DefaultValue(true)] 33 | public bool AutomaticRecoveryEnabled { get; set; } = true; 34 | 35 | [JsonProperty("rabbitmq-timeout")] 36 | public int RequestedConnectionTimeout { get; set; } = 5000; 37 | 38 | [JsonProperty("rabbitmq-consumer-tag"), DefaultValue(null)] 39 | public string ConsumerTag { get; set; } 40 | 41 | public AlphaStreamCredentials() 42 | { 43 | } 44 | 45 | public AlphaStreamCredentials(string hostName, 46 | int port, 47 | string username, 48 | string password, 49 | string exchangeName, 50 | string virtualHost = "/", 51 | bool automaticRecoveryEnabled = true, 52 | int requestedConnectionTimeout = 5000, 53 | string consumerTag = null 54 | ) 55 | { 56 | HostName = hostName; 57 | Port = port; 58 | Username = username; 59 | Password = password; 60 | ExchangeName = exchangeName; 61 | VirtualHost = virtualHost; 62 | AutomaticRecoveryEnabled = automaticRecoveryEnabled; 63 | RequestedConnectionTimeout = requestedConnectionTimeout; 64 | 65 | // uniquely identify this consumer 66 | ConsumerTag = consumerTag ?? Guid.NewGuid().ToString("N"); 67 | } 68 | 69 | /// 70 | /// Creates a new instance based on the config.json file 71 | /// 72 | public static AlphaStreamCredentials FromConfiguration() 73 | { 74 | if (!File.Exists("config.json")) 75 | { 76 | throw new FileNotFoundException("Please specify 'alpha-credentials-path' in 'config.json'"); 77 | } 78 | 79 | var config = JObject.Parse(File.ReadAllText("config.json")); 80 | var credentialsPath = config["alpha-credentials-path"]; 81 | if (credentialsPath == null) 82 | { 83 | throw new Exception("Please specify 'alpha-credentials-path' in 'config.json'"); 84 | } 85 | 86 | return FromFile(credentialsPath.Value()); 87 | } 88 | 89 | /// 90 | /// Creates a new instance based on the provided config json file 91 | /// 92 | public static AlphaInsightsStreamCredentials FromFile(string path) 93 | { 94 | if (!File.Exists(path)) 95 | { 96 | throw new FileNotFoundException($"AlphaInsightsStreamCredentials file not found: {path}"); 97 | } 98 | 99 | return JsonConvert.DeserializeObject(File.ReadAllText(path)); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/HeartbeatReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QuantConnect.AlphaStream 4 | { 5 | /// 6 | /// Event arguments fired when a new heartbeat is received by the streaming client 7 | /// 8 | public class HeartbeatReceivedEventArgs : EventArgs 9 | { 10 | /// 11 | /// Gets the alpha id that produced the heartbeat 12 | /// 13 | public string AlphaId { get; } 14 | 15 | /// 16 | /// Gets the algorithm id for the given alpha 17 | /// 18 | public string AlgorithmId { get; } 19 | 20 | /// 21 | /// Gets the machine time of the heartbeat 22 | /// 23 | public DateTime MachineTime { get; set; } 24 | 25 | /// 26 | /// Initializes a new instance of the class 27 | /// 28 | /// The alpha id that produced the heartbeat 29 | /// The algorithm id for the given alpha 30 | /// The machine time of the heartbeat 31 | public HeartbeatReceivedEventArgs(string alphaId, string algorithmId, DateTime? machineTime) 32 | { 33 | AlphaId = alphaId; 34 | AlgorithmId = algorithmId; 35 | if (machineTime.HasValue) 36 | { 37 | MachineTime = machineTime.Value; 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/IAlphaInsightsStreamClient.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Requests; 2 | 3 | namespace QuantConnect.AlphaStream 4 | { 5 | /// 6 | /// Client used to receive streaming alpha insights. 7 | /// This client can subscribe and unsubscribe to individual alpha streams that have already been purchased. 8 | /// 9 | /// Kept for backwards compatibility 10 | public interface IAlphaInsightsStreamClient 11 | { 12 | /// 13 | /// Add an alpha insight stream to this client. 14 | /// The requested alpha stream must already be purchased. 15 | /// 16 | /// Request defining the alpha id of the stream to add 17 | bool AddAlphaStream(AddInsightsStreamRequest request); 18 | 19 | /// 20 | /// Removes an alpha insight stream from this client 21 | /// 22 | /// Request defining which stream to remove 23 | bool RemoveAlphaStream(RemoveInsightsStreamRequest request); 24 | } 25 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/IAlphaStreamClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using QuantConnect.AlphaStream.Requests; 3 | 4 | namespace QuantConnect.AlphaStream 5 | { 6 | /// 7 | /// Client used to receive streaming alpha insights, orders and order events. 8 | /// This client can subscribe and unsubscribe to individual alpha streams that have already been purchased. 9 | /// 10 | public interface IAlphaStreamClient : IDisposable 11 | { 12 | /// 13 | /// Event fired for each insight received 14 | /// 15 | event EventHandler InsightReceived; 16 | 17 | /// 18 | /// Event fired when a heartbeat is received 19 | /// 20 | event EventHandler HeartbeatReceived; 21 | 22 | /// 23 | /// Event fired when a new Order or an update is received 24 | /// 25 | event EventHandler OrderReceived; 26 | 27 | /// 28 | /// Connect to the streaming insights server 29 | /// 30 | void Connect(); 31 | 32 | /// 33 | /// Add an alpha stream to this client. 34 | /// The requested alpha stream must already be purchased. 35 | /// 36 | /// Request defining the alpha id of the stream to add 37 | bool AddAlphaStream(AddAlphaStreamRequest request); 38 | 39 | /// 40 | /// Removes an alpha stream from this client 41 | /// 42 | /// Request defining which stream to remove 43 | bool RemoveAlphaStream(RemoveAlphaStreamRequest request); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/IAlphaStreamRestClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using QuantConnect.AlphaStream.Infrastructure; 3 | 4 | namespace QuantConnect.AlphaStream 5 | { 6 | public interface IAlphaStreamRestClient 7 | { 8 | Task Execute(IRequest request); 9 | } 10 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/AlphaServiceException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Net; 6 | using Newtonsoft.Json; 7 | using QuantConnect.AlphaStream.Models; 8 | using RestSharp; 9 | 10 | namespace QuantConnect.AlphaStream.Infrastructure 11 | { 12 | /// 13 | /// Exception thrown while communicating with the QuantConnect Alpha Streams REST Service. 14 | /// 15 | public class AlphaServiceException : Exception 16 | { 17 | /// 18 | /// The resposne content. 19 | /// 20 | public string Content { get; } 21 | 22 | /// 23 | /// The response status code. 24 | /// 25 | public HttpStatusCode StatusCode { get; } 26 | 27 | /// 28 | /// Error messages includes with the response. 29 | /// 30 | public List Messages { get; } = new List(); 31 | 32 | public AlphaServiceException(string message, HttpStatusCode statusCode, string content, IEnumerable messages) 33 | : base(message) 34 | { 35 | Content = content; 36 | StatusCode = statusCode; 37 | Messages.AddRange(messages); 38 | } 39 | 40 | public static AlphaServiceException ForResponse(IRestResponse response) 41 | { 42 | var messages = new List(); 43 | try 44 | { 45 | // try to parse as a generic api response and add error messages 46 | var apiResonse = JsonConvert.DeserializeObject(response.Content); 47 | if (apiResonse?.Messages?.Count > 0) 48 | { 49 | foreach (var message in apiResonse.Messages) 50 | { 51 | messages.Add(message); 52 | Trace.TraceError(message); 53 | } 54 | } 55 | } 56 | catch 57 | { 58 | } 59 | 60 | var msg = messages.Any() ? messages[0] : "Received an unexpected response from the server."; 61 | return new AlphaServiceException(msg, response.StatusCode, response.Content, messages); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/AlphaStreamInsightJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using QuantConnect.Algorithm.Framework.Alphas; 3 | using QuantConnect.Algorithm.Framework.Alphas.Serialization; 4 | using QuantConnect.AlphaStream.Models; 5 | using QuantConnect.Util; 6 | 7 | namespace QuantConnect.AlphaStream.Infrastructure 8 | { 9 | /// 10 | /// Defines how insights should be serialized to json 11 | /// 12 | public class AlphaStreamInsightJsonConverter : TypeChangeJsonConverter 13 | { 14 | /// 15 | /// Convert the input value to a value to be serialized 16 | /// 17 | /// The input value to be converted before serialization 18 | /// A new instance of TResult that is to be serialized 19 | protected override SerializedAlphaStreamInsight Convert(AlphaStreamInsight value) 20 | { 21 | return new SerializedAlphaStreamInsight(value); 22 | } 23 | 24 | /// 25 | /// Converts the input value to be deserialized 26 | /// 27 | /// The deserialized value that needs to be converted to T 28 | /// The converted value 29 | protected override AlphaStreamInsight Convert(SerializedAlphaStreamInsight value) 30 | { 31 | return AlphaStreamInsight.FromSerializedAlphaStreamInsight(value); 32 | } 33 | } 34 | 35 | public class SerializedAlphaStreamInsight : SerializedInsight 36 | { 37 | /// 38 | /// Enum indicating the Insight creation moment. 39 | /// 40 | [JsonProperty("source")] 41 | public Source Source { get; } 42 | 43 | /// 44 | /// Initializes a new default instance of the class 45 | /// 46 | public SerializedAlphaStreamInsight() 47 | { 48 | } 49 | 50 | public SerializedAlphaStreamInsight(AlphaStreamInsight insight) : base(insight) 51 | { 52 | Source = insight.Source; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/AttributeRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using RestSharp; 5 | 6 | namespace QuantConnect.AlphaStream.Infrastructure 7 | { 8 | /// 9 | /// Rest request object that uses attributes to define the endpoint and parameters of the request 10 | /// 11 | /// The expected response type from the server 12 | public abstract class AttributeRequest : IRequest 13 | { 14 | /// 15 | /// Converts this request object into a rest sharp request object. 16 | /// 17 | /// The rest sharp request object 18 | public IRestRequest ToRestRequest() 19 | { 20 | var type = GetType(); 21 | 22 | // resolve endpoint 23 | var endpoint = type.GetCustomAttribute(); 24 | if (endpoint == null) 25 | { 26 | throw new InvalidOperationException($"Request types must be decorated with the {nameof(EndpointAttribute)}."); 27 | } 28 | 29 | // resolve parameters from request object 30 | var parameters = type.GetProperties().Select(p => new 31 | { 32 | property = p, 33 | parameter = p.GetCustomAttribute() 34 | }); 35 | 36 | // apply parameters from request object to rest request 37 | var restRequest = new RestRequest(endpoint.Resource, endpoint.Method); 38 | foreach (var item in parameters.Where(item => item.parameter != null)) 39 | { 40 | // resolve parameter value 41 | var value = item.property.GetValue(this); 42 | 43 | // set parameter on rest request 44 | item.parameter.SetParameter(restRequest, item.property, value); 45 | } 46 | 47 | return restRequest; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/BodyParameterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using Newtonsoft.Json.Linq; 5 | using RestSharp; 6 | 7 | namespace QuantConnect.AlphaStream.Infrastructure 8 | { 9 | [AttributeUsage(AttributeTargets.Property)] 10 | public class BodyParameterAttribute : ParameterAttribute 11 | { 12 | public BodyParameterAttribute(string name) 13 | : base(name) 14 | { 15 | } 16 | 17 | public override void SetParameter(IRestRequest request, MemberInfo member, object value) 18 | { 19 | if (value == null) 20 | { 21 | return; 22 | } 23 | 24 | var jtoken = JToken.FromObject(value); 25 | var body = request.Parameters.SingleOrDefault(p => p.Type == ParameterType.RequestBody); 26 | if (body == null) 27 | { 28 | var jobject = new JObject 29 | { 30 | [Name] = jtoken 31 | }; 32 | request.AddParameter("application/json", jobject, "application/json", ParameterType.RequestBody); 33 | } 34 | else 35 | { 36 | // update the request body to include this new property 37 | var bodyJToken = body.Value is JObject ? (JObject) body.Value : JObject.Parse(body.Value.ToString()); 38 | bodyJToken[Name] = jtoken; 39 | body.Value = bodyJToken; 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/EndpointAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RestSharp; 3 | 4 | namespace QuantConnect.AlphaStream.Infrastructure 5 | { 6 | /// 7 | /// Specifies an endpoint for a REST request 8 | /// 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class EndpointAttribute : Attribute 11 | { 12 | /// 13 | /// Gets the for this endpoint 14 | /// 15 | public Method Method { get; } 16 | 17 | /// 18 | /// Gets the resource path 19 | /// 20 | public string Resource { get; } 21 | 22 | /// 23 | /// Initializes a new instance of the class 24 | /// 25 | /// The HTTP verb 26 | /// The resource path 27 | public EndpointAttribute(Method method, string resource) 28 | { 29 | Method = method; 30 | Resource = resource; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/HyphenSeparatedQueryParameterNamingConvention.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | using System.Runtime.Serialization; 4 | using Newtonsoft.Json; 5 | 6 | namespace QuantConnect.AlphaStream.Infrastructure 7 | { 8 | /// 9 | /// Defines the 'hyphen separated' naming convention for complex query parameters. 10 | /// 11 | public class HyphenSeparatedQueryParameterNamingConvention : IQueryParameterNamingConvention 12 | { 13 | /// 14 | /// Creates an enumerable of parameters resolved from the specified value. 15 | /// In the typical case, properties are read from the value and each emitted 16 | /// as key/value pairs representing the desired query parameter name/value 17 | /// 18 | /// The member info corresponding to the specified value 19 | /// The complex value to be decomposed into name/value pairs 20 | /// An enumerable of all name/value pairs resolved from the specified complex query parameter value 21 | public IEnumerable GetQueryNameValuePairs(MemberInfo member, object value) 22 | { 23 | var context = GetQueryParameterName(member); 24 | foreach (var descriptor in GetQueryNameValuePairs(value, context)) 25 | { 26 | yield return descriptor; 27 | } 28 | } 29 | 30 | /// 31 | /// Recursive call that walks through properties and if they're complex type, then through their properties as well 32 | /// 33 | private IEnumerable GetQueryNameValuePairs(object value, string context) 34 | { 35 | if (value == null) 36 | { 37 | yield break; 38 | } 39 | 40 | foreach (var property in value.GetType().GetProperties()) 41 | { 42 | var propertyName = GetQueryParameterName(property); 43 | var name = context.Length > 0 44 | ? $"{context}-{propertyName}" 45 | : propertyName; 46 | 47 | var propertyValue = property.GetValue(value); 48 | if (property.PropertyType.IsClass && property.PropertyType != typeof(string)) 49 | { 50 | // recurse on complex sub-types 51 | foreach (var descriptor in GetQueryNameValuePairs(propertyValue, name)) 52 | { 53 | yield return descriptor; 54 | } 55 | } 56 | else 57 | { 58 | yield return new QueryParameterDescriptor(name, propertyValue, property); 59 | } 60 | } 61 | } 62 | 63 | /// 64 | /// Resolves the query parameter name to use from attributes, defaulting to the member name if none found 65 | /// 66 | private string GetQueryParameterName(MemberInfo property) 67 | { 68 | var queryParameterAttribute = property.GetCustomAttribute(); 69 | if (queryParameterAttribute != null) 70 | { 71 | return queryParameterAttribute.Name; 72 | } 73 | 74 | var jsonPropertyAttribute = property.GetCustomAttribute(); 75 | if (jsonPropertyAttribute != null) 76 | { 77 | return jsonPropertyAttribute.PropertyName; 78 | } 79 | 80 | var dataMemberAttribute = property.GetCustomAttribute(); 81 | if (dataMemberAttribute != null) 82 | { 83 | return dataMemberAttribute.Name; 84 | } 85 | 86 | return property.Name; 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/IQueryParameterNamingConvention.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | 4 | namespace QuantConnect.AlphaStream.Infrastructure 5 | { 6 | /// 7 | /// Defines a naming convention for projecting a complex type into a query string. 8 | /// 9 | public interface IQueryParameterNamingConvention 10 | { 11 | /// 12 | /// Creates an enumerable of parameters resolved from the specified value. 13 | /// In the typical case, properties are read from the value and each emitted 14 | /// as key/value pairs representing the desired query parameter name/value 15 | /// 16 | /// The member info corresponding to the specified value 17 | /// The complex value to be decomposed into name/value pairs 18 | /// An enumerable of all name/value pairs resolved from the specified complex query parameter value 19 | IEnumerable GetQueryNameValuePairs(MemberInfo member, object value); 20 | } 21 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/IRequest.cs: -------------------------------------------------------------------------------- 1 | using RestSharp; 2 | 3 | namespace QuantConnect.AlphaStream.Infrastructure 4 | { 5 | /// 6 | /// Request object that is convertible into a rest sharp request object. 7 | /// 8 | /// Response type 9 | public interface IRequest 10 | { 11 | /// 12 | /// Converts this request object into a rest sharp request object. 13 | /// 14 | /// The rest sharp request object 15 | IRestRequest ToRestRequest(); 16 | } 17 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/ParameterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Infrastructure 6 | { 7 | /// 8 | /// Defines a parameter in a request 9 | /// 10 | [AttributeUsage(AttributeTargets.Property)] 11 | public abstract class ParameterAttribute : Attribute 12 | { 13 | /// 14 | /// Gets the name of this parameter 15 | /// 16 | public string Name { get; } 17 | 18 | /// 19 | /// Initializes a new instance of the class 20 | /// 21 | /// The name of the parameter 22 | protected ParameterAttribute(string name) 23 | { 24 | Name = name; 25 | } 26 | 27 | /// 28 | /// Set the parameter on the request object 29 | /// 30 | /// The rest request object 31 | /// The member of the value 32 | /// The value to be added as a parameter 33 | public abstract void SetParameter(IRestRequest request, MemberInfo member, object value); 34 | } 35 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/PathParameterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Reflection; 4 | using RestSharp; 5 | 6 | namespace QuantConnect.AlphaStream.Infrastructure 7 | { 8 | /// 9 | /// Defines a parameter as part of the url path 10 | /// 11 | public class PathParameterAttribute : ParameterAttribute 12 | { 13 | /// 14 | /// Initializes a new instance of the class 15 | /// 16 | /// The name of the parameter 17 | public PathParameterAttribute(string name) 18 | : base(name) 19 | { 20 | } 21 | 22 | /// 23 | /// Set the parameter on the request object in the url path 24 | /// 25 | /// The rest request object 26 | /// The member of the value 27 | /// The value to be added as a parameter 28 | public override void SetParameter(IRestRequest request, MemberInfo member, object value) 29 | { 30 | if (ReferenceEquals(null, value)) 31 | { 32 | return; 33 | } 34 | 35 | if (value is string || !(value is IEnumerable)) 36 | { 37 | request.AddUrlSegment(Name, value.ToString()); 38 | } 39 | else 40 | { 41 | throw new ArgumentException("Path parameters must be scalar values."); 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/QueryParameterDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace QuantConnect.AlphaStream.Infrastructure 4 | { 5 | /// 6 | /// Provides information about a query parameter, including it's name, value and possibly 7 | /// the member that produced the value, such as a property info object. 8 | /// 9 | public class QueryParameterDescriptor 10 | { 11 | public string Name { get; } 12 | public object Value { get; } 13 | public MemberInfo Member { get; } 14 | 15 | /// 16 | /// Initializes a new instance of the class 17 | /// 18 | /// The query parameter name 19 | /// The query parameter value 20 | /// The member info where the value came from 21 | public QueryParameterDescriptor(string name, object value, MemberInfo member) 22 | { 23 | Name = name; 24 | Value = value; 25 | Member = member; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/RestRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Infrastructure 6 | { 7 | /// 8 | /// Provides extension methods on 9 | /// 10 | public static class RestRequestExtensions 11 | { 12 | /// 13 | /// Gets the single parameter of tpe or null if none found. 14 | /// 15 | /// The rest request object 16 | /// The body parameter's value or null 17 | public static string GetBody(this IRestRequest request) 18 | { 19 | var body = request.GetParameters(ParameterType.RequestBody).SingleOrDefault(); 20 | return body?.Value.ToString(); 21 | } 22 | 23 | /// 24 | /// Gets all parameters of the specified type 25 | /// 26 | /// The rest request object 27 | /// The parameter type to seach for 28 | /// An enumerable of the matching parameters 29 | public static IEnumerable GetParameters(this IRestRequest request, ParameterType type) 30 | { 31 | return request.Parameters.Where(p => p.Type == type); 32 | } 33 | 34 | /// 35 | /// Combines the path and query together into the string that will be used when the request is executed 36 | /// 37 | /// The rest request object 38 | /// The combined path and query from the rest request object 39 | public static string GetPathAndQuery(this IRestRequest request) 40 | { 41 | var resource = request.Resource; 42 | 43 | // replace path parameters 44 | foreach (var urlSegment in request.GetParameters(ParameterType.UrlSegment)) 45 | { 46 | resource = resource.Replace($"{{{urlSegment.Name}}}", urlSegment.Value.ToString()); 47 | } 48 | 49 | // construct query string 50 | var query = request.GetParameters(ParameterType.QueryString).Aggregate((string) null, (c, p) => $"{(c == null ? "?" : c + "&")}{p.Name}={p.Value}"); 51 | 52 | return $"{resource}{query}"; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using Newtonsoft.Json; 4 | using Newtonsoft.Json.Linq; 5 | 6 | namespace QuantConnect.AlphaStream.Infrastructure 7 | { 8 | public static class StringExtensions 9 | { 10 | public static IEnumerable AsLines(this string str) 11 | { 12 | using (var reader = new StringReader(str)) 13 | { 14 | string line; 15 | while ((line = reader.ReadLine()) != null) 16 | { 17 | yield return line; 18 | } 19 | } 20 | } 21 | 22 | public static string FormatAsJsonIfPossible(this string str) 23 | { 24 | try 25 | { 26 | var jToken = JToken.Parse(str); 27 | return jToken.ToString(Formatting.Indented); 28 | } 29 | catch 30 | { 31 | return str; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Infrastructure/Time.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QuantConnect.AlphaStream.Infrastructure 4 | { 5 | public static class Time 6 | { 7 | public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 8 | 9 | public static long ToUnixTime(this DateTime utcNow) 10 | { 11 | var epoch = utcNow - UnixEpoch; 12 | return (long)epoch.TotalSeconds; 13 | } 14 | 15 | public static DateTime ToDateTime(this long stamp) 16 | { 17 | return UnixEpoch.AddSeconds(stamp); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/InsightReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using QuantConnect.AlphaStream.Models; 3 | 4 | namespace QuantConnect.AlphaStream 5 | { 6 | /// 7 | /// Event arguments fired when a new insight is received by the streaming client 8 | /// 9 | public class InsightReceivedEventArgs : EventArgs 10 | { 11 | /// 12 | /// Gets the alpha id that produced the insight 13 | /// 14 | public string AlphaId { get; } 15 | 16 | /// 17 | /// Gets the insight 18 | /// 19 | public AlphaStreamInsight Insight { get; } 20 | 21 | /// 22 | /// Initializes a new instance of the class 23 | /// 24 | /// The alpha id tht produced the insight 25 | /// The insight 26 | public InsightReceivedEventArgs(string alphaId, AlphaStreamInsight insight) 27 | { 28 | AlphaId = alphaId; 29 | Insight = insight; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/AlphaStatus.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System.Runtime.Serialization; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Alpha Status 9 | /// 10 | [JsonConverter(typeof(StringEnumConverter), true)] 11 | public enum AlphaStatus 12 | { 13 | /// 14 | /// Unknown status 15 | /// 16 | [EnumMember(Value = "")] Unknown, 17 | 18 | /// 19 | /// Running alpha model 20 | /// 21 | [EnumMember(Value = "running")] Running, 22 | 23 | /// 24 | /// Stopped alpha model 25 | /// 26 | [EnumMember(Value = "stopped")] Stopped 27 | } 28 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/AlphaStreamInsight.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using QuantConnect.Algorithm.Framework.Alphas; 4 | using QuantConnect.AlphaStream.Infrastructure; 5 | 6 | namespace QuantConnect.AlphaStream.Models 7 | { 8 | /// 9 | /// Individual prediction from an Alpha. 10 | /// 11 | [JsonConverter(typeof(AlphaStreamInsightJsonConverter))] 12 | public class AlphaStreamInsight : Insight 13 | { 14 | /// 15 | /// Enum indicating the Insight creation moment. 16 | /// 17 | [JsonProperty("source")] 18 | public Source Source { get; set; } = Source.Unknown; 19 | 20 | public AlphaStreamInsight() : base(Symbol.Empty, TimeSpan.Zero, InsightType.Price, InsightDirection.Flat) 21 | { 22 | } 23 | 24 | public AlphaStreamInsight(DateTime generatedTimeUtc, Symbol symbol, TimeSpan period, InsightType type, InsightDirection direction, 25 | double? magnitude, double? confidence, string sourceModel = null, double? weight = null) : 26 | base(generatedTimeUtc, symbol, period, type, direction, magnitude, confidence, sourceModel, weight) 27 | { 28 | } 29 | 30 | /// 31 | /// Creates a new object from the specified serialized form 32 | /// 33 | /// The insight DTO 34 | /// A new insight containing the information specified 35 | public static AlphaStreamInsight FromSerializedAlphaStreamInsight(SerializedAlphaStreamInsight serializedInsight) 36 | { 37 | var insight = FromSerializedInsight(serializedInsight); 38 | 39 | return new AlphaStreamInsight( 40 | insight.GeneratedTimeUtc, 41 | insight.Symbol, 42 | insight.Period, 43 | insight.Type, 44 | insight.Direction, 45 | insight.Magnitude, 46 | insight.Confidence, 47 | insight.SourceModel, 48 | insight.Weight 49 | ) 50 | { 51 | Id = insight.Id, 52 | CloseTimeUtc = insight.CloseTimeUtc, 53 | EstimatedValue = insight.EstimatedValue, 54 | ReferenceValue = insight.ReferenceValue, 55 | ReferenceValueFinal = insight.ReferenceValueFinal, 56 | GroupId = insight.GroupId, 57 | Score = insight.Score, 58 | Source = serializedInsight.Source 59 | }; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/ApiResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text; 3 | using Newtonsoft.Json; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Generic success/error response message from the API. 9 | /// 10 | public class ApiResponse 11 | { 12 | /// 13 | /// Boolean indicating success 14 | /// 15 | [JsonProperty("success")] 16 | public bool Success { get; set; } 17 | 18 | /// 19 | /// Single message from the API. 20 | /// 21 | [JsonProperty("message")] 22 | public string Message { get; set; } 23 | 24 | /// 25 | /// Array of error messages from the API. 26 | /// 27 | [JsonProperty("messages")] 28 | public List Messages { get; set; } = new List(); 29 | 30 | /// 31 | /// Returns a string that represents the ApiResponse object 32 | /// 33 | /// A string that represents the Alpha object 34 | public override string ToString() 35 | { 36 | if (Success) 37 | { 38 | return "Successful response from the API"; 39 | } 40 | 41 | var stringBuilder = new StringBuilder("Failed response from the API: "); 42 | if (string.IsNullOrWhiteSpace(Message)) 43 | { 44 | stringBuilder.Append(Message); 45 | } 46 | 47 | if (Messages.Count > 0) 48 | { 49 | stringBuilder.Append(string.Join(", ", Messages)); 50 | } 51 | 52 | return stringBuilder.ToString(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Bid.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using QuantConnect.Util; 3 | using System; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Information on a specific bid made to license an Alpha 9 | /// 10 | public class Bid 11 | { 12 | /// 13 | /// Unique ID of the Bid 14 | /// 15 | [JsonProperty("id")] 16 | public int Id { get; set; } 17 | 18 | /// 19 | /// Expiration time of the bid. 20 | /// 21 | [JsonProperty("good-until-time"), JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 22 | public DateTime GoodUntil { get; set; } 23 | 24 | /// 25 | /// Allocation that the alpha will be licensed to 26 | /// 27 | [JsonProperty("allocation")] 28 | public decimal Allocation { get; set; } 29 | 30 | /// 31 | /// Period that the alpha will be licensed to (in days) 32 | /// 33 | [JsonProperty("license-period", NullValueHandling = NullValueHandling.Ignore)] 34 | public decimal LicensePeriod { get; set; } 35 | 36 | /// 37 | /// The maximum bid price per 4-week period 38 | /// 39 | [JsonProperty("maximum-price")] 40 | public decimal MaximumPrice { get; set; } 41 | 42 | /// 43 | /// Returns a string that represents the Bid object 44 | /// 45 | /// A string that represents the Bid object 46 | public override string ToString() 47 | { 48 | return $"Bid of ${MaximumPrice} for a ${Allocation} allocation to license " + 49 | $"for the next {LicensePeriod} days is good until {GoodUntil}."; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/BidResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace QuantConnect.AlphaStream.Models 4 | { 5 | /// 6 | /// Result of a bid to license an Alpha 7 | /// 8 | public class BidResponse : ApiResponse 9 | { 10 | /// 11 | /// Capacity allocated if the bid is successful 12 | /// 13 | [JsonProperty("capacity-allocated")] 14 | public decimal CapacityAllocated { get; set; } 15 | 16 | /// 17 | /// True if the bid resulted in a new license 18 | /// 19 | [JsonProperty("licensed")] 20 | public bool Licensed { get; set; } 21 | 22 | /// 23 | /// True if the out bid 24 | /// 25 | [JsonProperty("Outbid")] 26 | public bool Outbid { get; set; } 27 | 28 | /// 29 | /// Returns a string that represents the BidResponse object 30 | /// 31 | /// A string that represents the BidResponse object 32 | public override string ToString() 33 | { 34 | if (!Success) 35 | { 36 | return base.ToString(); 37 | } 38 | 39 | if (Licensed) 40 | { 41 | return $"Congratulations! Your bid on the alpha was successful and your license with a ${CapacityAllocated} allocation for the alphas has started."; 42 | } 43 | 44 | if (Outbid) 45 | { 46 | return "Your bid for shares was recently outbid and we believe you may not win the final auction."; 47 | } 48 | 49 | return "Not licensed nor outbid. Please contact support@quantconnect.com"; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/BidResult.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using QuantConnect.Util; 3 | using System; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Result of a bid to license an Alpha 9 | /// 10 | public class BidResult 11 | { 12 | /// 13 | /// True if the bid is successful 14 | /// 15 | [JsonProperty("success")] 16 | public bool Success { get; set; } 17 | 18 | /// 19 | /// Information about the active bid 20 | /// 21 | [JsonProperty("active-bid")] 22 | public Bid ActiveBid { get; set; } 23 | 24 | /// 25 | /// Time that the next auction will occur 26 | /// 27 | [JsonProperty("next-auction-time"), JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 28 | public DateTime NextAuctionTime { get; set; } 29 | 30 | /// 31 | /// Alpha's capacity for the next auction 32 | /// 33 | [JsonProperty("next-auction-capacity")] 34 | public decimal NextAuctionCapacity { get; set; } 35 | 36 | /// 37 | /// Minimum capital required to place a bid 38 | /// 39 | [JsonProperty("minimum-capital-required")] 40 | public decimal MinimumCapitalRequired { get; set; } 41 | 42 | /// 43 | /// Returns a string that represents the BidResult object 44 | /// 45 | /// A string that represents the BidResult object 46 | public override string ToString() 47 | { 48 | var activeBid = Success && ActiveBid != null ? $"Active bid: {ActiveBid}" : "No active bid"; 49 | return $"{activeBid} Next auction at {NextAuctionTime} for ${NextAuctionCapacity}. Minimum capital required : ${MinimumCapitalRequired}"; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/DateRange.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using QuantConnect.Util; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Specifies a date range to search 9 | /// 10 | public class DateRange 11 | where T : struct 12 | { 13 | /// 14 | /// Lower bound of the search criteria. 15 | /// 16 | [JsonProperty("minimum", DefaultValueHandling = DefaultValueHandling.Ignore)] 17 | [JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 18 | public DateTime? Minimum { get; set; } 19 | 20 | /// 21 | /// pper bound of the search criteria. 22 | /// 23 | [JsonProperty("maximum", DefaultValueHandling = DefaultValueHandling.Ignore)] 24 | [JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 25 | public DateTime? Maximum { get; set; } 26 | 27 | /// 28 | /// Initializes a new instance of the class 29 | /// 30 | public DateRange() 31 | { 32 | } 33 | 34 | /// 35 | /// Initializes a new instance of the class 36 | /// 37 | /// The minimum value 38 | /// The maximum value 39 | public DateRange(DateTime? minimum, DateTime? maximum) 40 | { 41 | Minimum = minimum; 42 | Maximum = maximum; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/EquityCurve.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QuantConnect.AlphaStream.Models 4 | { 5 | public class EquityCurve 6 | { 7 | /// 8 | /// Timestamp of equity curve point 9 | /// 10 | public DateTime Time { get; } 11 | 12 | /// 13 | /// Alpha Id. Unified equity curve has data of more than one version of an Alpha. 14 | /// 15 | public string Id { get; } 16 | 17 | /// 18 | /// Dollar value of the equity 19 | /// 20 | public double Equity { get; } 21 | 22 | /// 23 | /// Sample of equity point (in-sample or live-trading) 24 | /// 25 | public string Sample { get; } 26 | 27 | /// 28 | /// Creates a new instance of EquityCurve 29 | /// 30 | /// Timestamp of equity curve point 31 | /// Dollar value of the equity 32 | /// Sample of equity point (in-sample or live-trading) 33 | /// Alpha Id. Unified equity curve has data of more than one version of an Alpha. 34 | public EquityCurve(DateTime time, double equity, string sample, string id) 35 | { 36 | Time = time; 37 | Equity = equity; 38 | Sample = sample; 39 | Id = id; 40 | } 41 | 42 | /// 43 | /// Returns a string that represents the EquityCurve object 44 | /// 45 | /// A string that represents the EquityCurve object 46 | public override string ToString() => $"{Time},{Equity},{Sample},{Id}"; 47 | } 48 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/InsightPackage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using System.Collections.Generic; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Wrapper packet to hold collection of Insight objects 9 | /// 10 | public class InsightPackage 11 | { 12 | /// 13 | /// Unique Alpha Id which generated this Insight 14 | /// 15 | [JsonProperty("alpha-id")] 16 | public string AlphaId { get; set; } 17 | 18 | /// 19 | /// Deploy id for this algorithm 20 | /// 21 | [JsonProperty("algorithm-id")] 22 | public string AlgorithmId { get; set; } 23 | 24 | /// 25 | /// Array of insights emitted at this timestep. 26 | /// 27 | [JsonProperty("insights")] 28 | public List Insights { get; set; } = new List(); 29 | 30 | /// 31 | /// Returns a string that represents the InsightPackage object 32 | /// 33 | /// A string that represents the InsightPackage object 34 | public override string ToString() 35 | { 36 | return $"{AlphaId} Algorithm Id: {AlgorithmId} {string.Join(Environment.NewLine, Insights)}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/NumberRange.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using Microsoft.Win32.SafeHandles; 3 | using Newtonsoft.Json; 4 | using NodaTime; 5 | 6 | namespace QuantConnect.AlphaStream.Models 7 | { 8 | /// 9 | /// Specifies a numeric range of values to search 10 | /// 11 | public class NumberRange 12 | where T : struct 13 | { 14 | /// 15 | /// Lower bound of the search criteria. 16 | /// 17 | [JsonProperty("minimum", DefaultValueHandling = DefaultValueHandling.Ignore)] 18 | public T? Minimum { get; set; } 19 | 20 | /// 21 | /// pper bound of the search criteria. 22 | /// 23 | [JsonProperty("maximum", DefaultValueHandling = DefaultValueHandling.Ignore)] 24 | public T? Maximum { get; set; } 25 | 26 | /// 27 | /// Initializes a new instance of the class 28 | /// 29 | public NumberRange() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class 35 | /// 36 | /// The minimum value 37 | /// The maximum value 38 | public NumberRange(T? minimum, T? maximum) 39 | { 40 | Minimum = minimum; 41 | Maximum = maximum; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Orders/AlphaStreamOrder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using Newtonsoft.Json; 5 | using QuantConnect.Orders; 6 | using QuantConnect.Orders.Serialization; 7 | 8 | namespace QuantConnect.AlphaStream.Models.Orders 9 | { 10 | public class AlphaStreamOrder : SerializedOrder 11 | { 12 | /// 13 | /// Specifies the source of this order, live trading/backtesting/out of sample 14 | /// 15 | [JsonProperty("source")] 16 | public Source Source { get; set; } = Source.Unknown; 17 | 18 | /// 19 | /// The orders 20 | /// 21 | [JsonProperty("events")] 22 | public List OrderEvents { get; set; } = new List(); 23 | 24 | /// 25 | /// Creates a new serialized order instance based on the provided order 26 | /// 27 | public AlphaStreamOrder() 28 | { 29 | } 30 | 31 | /// 32 | /// Creates a new serialized order instance based on the provided order 33 | /// 34 | public AlphaStreamOrder(Order order, string algorithmId) : base(order, algorithmId) 35 | { 36 | } 37 | 38 | /// 39 | /// Returns a string that represents the current object. 40 | /// 41 | public override string ToString() 42 | { 43 | var stringBuilder = new StringBuilder(); 44 | 45 | stringBuilder.Append($"ID: {Id} Source '{Source}' Symbol: {Symbol} Status: {Status} CreatedTime: {CreatedTime} Direction {Direction} Quantity {Quantity} Type: {Type} TimeInForceType: {TimeInForceType}"); 46 | 47 | if (TimeInForceExpiry.HasValue) 48 | { 49 | stringBuilder.Append($" TimeInForceExpiry: {TimeInForceExpiry}"); 50 | } 51 | 52 | if (BrokerId.Count > 0) 53 | { 54 | stringBuilder.Append($" BrokerId: [{string.Join(",", BrokerId)}]"); 55 | } 56 | 57 | if (Price != 0) 58 | { 59 | stringBuilder.Append($" Price: {Price} {PriceCurrency}"); 60 | } 61 | 62 | if (ContingentId != 0) 63 | { 64 | stringBuilder.Append($" ContingentId: {ContingentId}"); 65 | } 66 | 67 | if (LastUpdateTime.HasValue) 68 | { 69 | stringBuilder.Append($" LastUpdateTime: {LastUpdateTime}"); 70 | } 71 | if (LastFillTime.HasValue) 72 | { 73 | stringBuilder.Append($" LastFillTime: {LastFillTime}"); 74 | } 75 | if (CanceledTime.HasValue) 76 | { 77 | stringBuilder.Append($" CanceledTime: {CanceledTime}"); 78 | } 79 | 80 | if (LimitPrice.HasValue) 81 | { 82 | stringBuilder.Append($" LimitPrice: {LimitPrice.Value}"); 83 | } 84 | if (StopPrice.HasValue) 85 | { 86 | stringBuilder.Append($" StopPrice: {StopPrice.Value}"); 87 | } 88 | 89 | if (SubmissionLastPrice != 0) 90 | { 91 | stringBuilder.Append($" SubmissionLastPrice: {SubmissionLastPrice}"); 92 | } 93 | if (SubmissionAskPrice != 0) 94 | { 95 | stringBuilder.Append($" SubmissionAskPrice: {SubmissionAskPrice}"); 96 | } 97 | if (SubmissionBidPrice != 0) 98 | { 99 | stringBuilder.Append($" SubmissionBidPrice: {SubmissionBidPrice}"); 100 | } 101 | 102 | if (!string.IsNullOrEmpty(Tag)) 103 | { 104 | stringBuilder.Append($" Tag: '{Tag}'"); 105 | } 106 | 107 | if (OrderEvents.Count > 0) 108 | { 109 | stringBuilder.Append(" OrderEvents: [{"); 110 | stringBuilder.Append(string.Join("},{", OrderEvents.Select(orderEvent => orderEvent.ToString(false)))); 111 | stringBuilder.Append("}]"); 112 | } 113 | 114 | return stringBuilder.ToString(); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Orders/AlphaStreamOrderEvent.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using QuantConnect.Orders; 3 | using QuantConnect.Orders.Serialization; 4 | using System.Text; 5 | 6 | namespace QuantConnect.AlphaStream.Models.Orders 7 | { 8 | public class AlphaStreamOrderEvent : SerializedOrderEvent 9 | { 10 | ///// 11 | ///// The unique order event id 12 | ///// 13 | [JsonProperty("id")] 14 | public override string Id => $"{AlgorithmId}-{HashId}-{OrderEventId}"; 15 | 16 | /// 17 | /// Id of the order this event comes from. 18 | /// 19 | [JsonProperty("order-id")] 20 | public string HashId { get; set; } 21 | 22 | public AlphaStreamOrderEvent() 23 | { 24 | } 25 | 26 | public AlphaStreamOrderEvent(OrderEvent orderEvent, string algorithmId) : base(orderEvent, algorithmId) 27 | { 28 | } 29 | 30 | /// 31 | /// Returns a string that represents the current object. 32 | /// Allows specifying if it should also add complete ID and Symbol. It's useful not to add them when called from parent Order 33 | /// 34 | public string ToString(bool extended) 35 | { 36 | var stringBuilder = new StringBuilder(); 37 | 38 | if (extended) 39 | { 40 | stringBuilder.Append($"Time: {Time} ID: {Id} Symbol: {Symbol} Status: {Status} Quantity {Quantity}"); 41 | } 42 | else 43 | { 44 | stringBuilder.Append($"Time: {Time} OrderId {OrderEventId} Status: {Status} Quantity {Quantity}"); 45 | } 46 | 47 | if (FillQuantity != 0) 48 | { 49 | stringBuilder.Append($" FillQuantity: {FillQuantity} FillPrice: {FillPrice} {FillPriceCurrency}"); 50 | } 51 | 52 | if (LimitPrice.HasValue) 53 | { 54 | stringBuilder.Append($" LimitPrice: {LimitPrice.Value}"); 55 | } 56 | if (StopPrice.HasValue) 57 | { 58 | stringBuilder.Append($" StopPrice: {StopPrice.Value}"); 59 | } 60 | 61 | if (OrderFeeAmount.HasValue) 62 | { 63 | stringBuilder.Append($" OrderFee: {OrderFeeAmount} {OrderFeeCurrency}"); 64 | } 65 | 66 | if (!string.IsNullOrEmpty(Message)) 67 | { 68 | stringBuilder.Append($" Message: '{Message}'"); 69 | } 70 | 71 | return stringBuilder.ToString(); 72 | } 73 | 74 | /// 75 | /// Returns a string that represents the current object. 76 | /// 77 | public override string ToString() 78 | { 79 | return ToString(true); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Project.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using Newtonsoft.Json; 4 | using QuantConnect.Util; 5 | 6 | namespace QuantConnect.AlphaStream.Models 7 | { 8 | /// 9 | /// Project object where the Alpha source resides. One Project can have multiple generated Alphas. 10 | /// 11 | public class Project 12 | { 13 | /// 14 | /// Alpha project author. 15 | /// 16 | [JsonProperty("author")] 17 | public Author Author { get; set; } 18 | 19 | /// 20 | /// Author assigned project name. 21 | /// 22 | [JsonProperty("name")] 23 | public string Name { get; set; } 24 | 25 | /// 26 | /// Unix timestamp when the project was created. 27 | /// 28 | [JsonProperty("created-time"), JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 29 | public DateTime CreatedTime { get; set; } 30 | 31 | /// 32 | /// Unix timestamp last time the project was opened/modified. 33 | /// 34 | [JsonProperty("last-modified-time"), JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 35 | public DateTime LastModifiedTime { get; set; } 36 | 37 | /// 38 | /// Returns a string that represents the Project object 39 | /// 40 | /// A string that represents the Project object 41 | public override string ToString() 42 | { 43 | var stringBuilder = new StringBuilder(Name); 44 | stringBuilder.Append($"{Environment.NewLine}Created Time:\t{CreatedTime}"); 45 | stringBuilder.Append($"{Environment.NewLine}Last time modified:\t{LastModifiedTime}"); 46 | stringBuilder.Append($"{Environment.NewLine}{Author}"); 47 | return stringBuilder.ToString(); 48 | } 49 | 50 | /// 51 | /// Returns a string that represents the Alpha object 52 | /// 53 | /// False if we want the short version 54 | /// A string that represents the Alpha object 55 | public string ToStringInline(bool extended = false) => ToString().Replace(Environment.NewLine, " "); 56 | } 57 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Range.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QuantConnect.AlphaStream.Models 4 | { 5 | /// 6 | /// Provides factory methods for creating number and date ranges 7 | /// 8 | public static class Range 9 | { 10 | public static NumberRange Create(int minimum, int maximum) 11 | { 12 | return new NumberRange(minimum, maximum); 13 | } 14 | 15 | public static NumberRange Create(int? minimum, int? maximum) 16 | { 17 | return new NumberRange(minimum, maximum); 18 | } 19 | 20 | public static NumberRange Create(long minimum, long maximum) 21 | { 22 | return new NumberRange(minimum, maximum); 23 | } 24 | 25 | public static NumberRange Create(long? minimum, long? maximum) 26 | { 27 | return new NumberRange(minimum, maximum); 28 | } 29 | 30 | public static NumberRange Create(decimal minimum, decimal maximum) 31 | { 32 | return new NumberRange(minimum, maximum); 33 | } 34 | 35 | public static NumberRange Create(decimal? minimum, decimal? maximum) 36 | { 37 | return new NumberRange(minimum, maximum); 38 | } 39 | 40 | public static NumberRange Create(double minimum, double maximum) 41 | { 42 | return new NumberRange(minimum, maximum); 43 | } 44 | 45 | public static NumberRange Create(double? minimum, double? maximum) 46 | { 47 | return new NumberRange(minimum, maximum); 48 | } 49 | 50 | public static DateRange Create(DateTime minimum, DateTime maximum) 51 | { 52 | return new DateRange(minimum, maximum); 53 | } 54 | 55 | public static DateRange Create(DateTime? minimum, DateTime? maximum) 56 | { 57 | return new DateRange(minimum, maximum); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/RuntimeError.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using QuantConnect.Util; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Individual error set for an Alpha in the QuantConnect Alpha Streams market 9 | /// 10 | public class RuntimeError 11 | { 12 | /// 13 | /// The unix timestamp of the production runtime error. 14 | /// 15 | [JsonProperty("time"), JsonConverter(typeof(DoubleUnixSecondsDateTimeJsonConverter))] 16 | public DateTime Time { get; set; } 17 | 18 | /// 19 | /// Error message string from the Alpha. 20 | /// 21 | [JsonProperty("error")] 22 | public string Error { get; set; } 23 | 24 | /// 25 | /// Stacktrace of the production error recorded from the Alpha. 26 | /// 27 | [JsonProperty("stacktrace")] 28 | public string StackTrace { get; set; } 29 | 30 | /// 31 | /// Returns a string that represents the RuntimeError object 32 | /// 33 | /// A string that represents the RuntimeError object 34 | public override string ToString() 35 | { 36 | return $"{Time}: {Error}{Environment.NewLine}StackTrace: {StackTrace}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Source.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Converters; 4 | 5 | namespace QuantConnect.AlphaStream.Models 6 | { 7 | /// 8 | /// Insight or Order source: in sample, out of sample, live trading. 9 | /// 10 | [JsonConverter(typeof(StringEnumConverter), true)] 11 | public enum Source 12 | { 13 | /// 14 | /// Generated from backtesting across historical data. 15 | /// 16 | [EnumMember(Value = "in sample")] InSample, 17 | 18 | /// 19 | /// Generated from running a backtest on out of sample data. 20 | /// 21 | [EnumMember(Value = "out of sample")] OutOfSample, 22 | 23 | /// 24 | /// Generated from forward trading environment recorded at the moment they were generated 25 | /// 26 | [EnumMember(Value = "live trading")] LiveTrading, 27 | 28 | /// 29 | /// Unknown source 30 | /// 31 | [EnumMember(Value = "")] Unknown, 32 | } 33 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Models/Tag.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace QuantConnect.AlphaStream.Models 4 | { 5 | public class Tag 6 | { 7 | [JsonProperty("matches")] 8 | public int Matches { get; set; } 9 | 10 | [JsonProperty("tag")] 11 | public string TagName { get; set; } 12 | 13 | /// 14 | /// Returns a string that represents the Tag object 15 | /// 16 | /// A string that represents the Tag object 17 | public override string ToString() 18 | { 19 | return $"{TagName} has {Matches} matches"; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/OrderReceivedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using QuantConnect.AlphaStream.Models; 3 | using QuantConnect.AlphaStream.Models.Orders; 4 | 5 | namespace QuantConnect.AlphaStream 6 | { 7 | /// 8 | /// Event arguments fired when a new Order or Order update is received by the streaming client 9 | /// 10 | public class OrderReceivedEventArgs : EventArgs 11 | { 12 | /// 13 | /// Gets the alpha id that produced the heartbeat 14 | /// 15 | public string AlphaId { get; } 16 | 17 | /// 18 | /// The current order state 19 | /// 20 | public AlphaStreamOrder Order { get; } 21 | 22 | /// 23 | /// Creates a new instance 24 | /// 25 | public OrderReceivedEventArgs(string alphaId, AlphaStreamOrder order) 26 | { 27 | Order = order; 28 | AlphaId = alphaId; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("QuantConnect.AlphaStream")] 8 | [assembly: AssemblyProduct("QuantConnect.AlphaStream")] 9 | [assembly: AssemblyCulture("")] 10 | 11 | // Setting ComVisible to false makes the types in this assembly not visible 12 | // to COM components. If you need to access a type in this assembly from 13 | // COM, set the ComVisible attribute to true on that type. 14 | [assembly: ComVisible(false)] 15 | 16 | // The following GUID is for the ID of the typelib if this project is exposed to COM 17 | [assembly: Guid("1c4a3a40-b5c9-4eb5-8776-c81ac10348e1")] 18 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/QuantConnect.AlphaStream.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Debug 4 | AnyCPU 5 | Library 6 | QuantConnect.AlphaStream 7 | net6.0 8 | false 9 | false 10 | QuantConnect Alpha Streams API SDK 11 | true 12 | 13 | 14 | bin\Debug\ 15 | 16 | 17 | bin\Release\ 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/AddAlphaStreamRequest.cs: -------------------------------------------------------------------------------- 1 | namespace QuantConnect.AlphaStream.Requests 2 | { 3 | /// 4 | /// Request used to add a new alpha to stream 5 | /// 6 | public class AddAlphaStreamRequest 7 | { 8 | /// 9 | /// The alpha id stream to request 10 | /// 11 | public string AlphaId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/AddInsightsStreamRequest.cs: -------------------------------------------------------------------------------- 1 | namespace QuantConnect.AlphaStream.Requests 2 | { 3 | /// 4 | /// Request used to add a new alpha to stream 5 | /// 6 | /// Kept for backwards compatibility 7 | public class AddInsightsStreamRequest : AddAlphaStreamRequest 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/AlphaStreamRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using RestSharp; 3 | 4 | namespace QuantConnect.AlphaStream.Requests 5 | { 6 | /// 7 | /// Streaming endpoint for insight predictions from the community. All subscribed Insights will be piped to this web socket connection 24/7. 8 | /// 9 | [Endpoint(Method.GET, "alpha/stream")] 10 | public class AlphaStreamRequest 11 | { 12 | } 13 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/CreateBidPriceRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | using System; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Create a bid price request. 10 | /// 11 | [Endpoint(Method.GET, "/alpha/{id}/prices/bids/create")] 12 | public class CreateBidPriceRequest : AttributeRequest 13 | { 14 | /// 15 | /// Unique id hash of an Alpha published to the marketplace. 16 | /// 17 | [PathParameter("id")] 18 | public string Id { get; set; } 19 | 20 | /// 21 | /// Unique id hash of an Alpha published to the marketplace. 22 | /// 23 | [QueryParameter("bid")] 24 | public int Bid { get; set; } 25 | 26 | /// 27 | /// Bid for the exclusive price (optional if shared is defined). 28 | /// 29 | [QueryParameter("allocation")] 30 | public int Allocation { get; set; } 31 | 32 | /// 33 | /// Bid for the shared price (optional if exclusive is defined). 34 | /// 35 | [QueryParameter("period")] 36 | public int Period { get; set; } 37 | 38 | /// 39 | /// Expiration time of the bid. 40 | /// 41 | [QueryParameter("good-until")] 42 | public long GoodUntil { get; set; } = DateTime.Today.AddDays(7).ToUnixTime(); 43 | 44 | /// 45 | /// Returns a string that represents the CreateBidPriceRequest object 46 | /// 47 | /// A string that represents the CreateBidPriceRequest object 48 | public override string ToString() 49 | { 50 | return $"Bid of ${Bid} for a ${Allocation} allocation to license the alpha {Id.Substring(0, 5)} " + 51 | $"for the next {Period} days is good until {GoodUntil}."; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaBidRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Fetch Alpha's latest bid 9 | /// 10 | [Endpoint(Method.GET, "alpha/{id}/prices/bids/read")] 11 | public class GetAlphaBidRequest : AttributeRequest 12 | { 13 | /// 14 | /// Unique id hash of an Alpha published to the marketplace. 15 | /// 16 | [PathParameter("id")] 17 | public string Id { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaByIdRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Read an individual information on an Alpha from the database based on the Alpha id. 9 | /// 10 | [Endpoint(Method.GET, "alpha/{id}")] 11 | public class GetAlphaByIdRequest : AttributeRequest 12 | { 13 | /// 14 | /// Unique id of an Alpha published to the marketplace. 15 | /// 16 | [PathParameter("id")] 17 | public string Id { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaEquityCurveRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using RestSharp; 3 | using System.Collections.Generic; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Fetch Alpha equity curve consisting of both backtest and live performance 9 | /// 10 | 11 | [Endpoint(Method.GET, "/alpha/{id}/equity")] 12 | 13 | public class GetAlphaEquityCurveRequest : AttributeRequest> 14 | { 15 | /// 16 | /// Unique id hash of an Alpha published to the marketplace. 17 | /// 18 | [PathParameter("id")] 19 | public string Id { get; set; } 20 | 21 | /// 22 | /// Preferred date format 23 | /// 24 | [QueryParameter("date-format")] 25 | public string DateFormat { get; set; } = "date"; 26 | 27 | /// 28 | /// Preferred format of returned equity curve 29 | /// 30 | [QueryParameter("format")] 31 | public string Format { get; set; } = "json"; 32 | 33 | /// 34 | /// Preferred content of returned equity curve. 35 | /// If False, returns data of one single Alpha with the following sampling: in sample, out of sample, and live trading 36 | /// If True, returns unified data of all versions of this Alpha with the live trading sampling only 37 | /// 38 | [QueryParameter("unified")] 39 | public bool Unified { get; set; } = true; 40 | 41 | /// 42 | /// Returns a string that represents the GetAlphaEquityCurveRequest object 43 | /// 44 | /// A string that represents the GetAlphaEquityCurveRequest object 45 | public override string ToString() 46 | { 47 | return $"{Id}: Date/time format {DateFormat} Data format: {Format}"; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaErrorsRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | using System.Collections.Generic; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Fetch Alpha runtime errors to help correlate unknown behavior or protect against exposure when an Alpha has a production issue. 10 | /// 11 | [Endpoint(Method.GET, "alpha/{id}/errors")] 12 | public class GetAlphaErrorsRequest : AttributeRequest> 13 | { 14 | /// 15 | /// Unique id hash of an Alpha published to the marketplace. 16 | /// 17 | [PathParameter("id")] 18 | public string Id { get; set; } 19 | 20 | /// 21 | /// Starting position for the search query. With very large datasets the results can be paginated and fetched in chunks starting from start. 22 | /// 23 | [QueryParameter("start")] 24 | public int Start { get; set; } = 0; 25 | } 26 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaInsightsRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using QuantConnect.AlphaStream.Infrastructure; 3 | using QuantConnect.AlphaStream.Models; 4 | using RestSharp; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Fetch the Alpha Insight list(backtest and live trading) track record since publication. 10 | /// 11 | [Endpoint(Method.GET, "alpha/{id}/insights")] 12 | public class GetAlphaInsightsRequest : AttributeRequest> 13 | { 14 | /// 15 | /// Unique id hash of an Alpha published to the marketplace. 16 | /// 17 | [PathParameter("id")] 18 | public string Id { get; set; } 19 | 20 | /// 21 | /// Starting position for the search query. With very large datasets the results can be paginated and fetched in chunks starting from start. 22 | /// 23 | [QueryParameter("start")] 24 | public int Start { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaListRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using RestSharp; 3 | using System.Collections.Generic; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Listing all alpha ids so you can maintain a dictionary and detect programatically when a new alpha is added to the API. 9 | /// 10 | [Endpoint(Method.GET, "alpha/list")] 11 | public class GetAlphaListRequest : AttributeRequest> 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaOrdersRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models.Orders; 3 | using RestSharp; 4 | using System.Collections.Generic; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Fetch the Alpha Orders and OrderEvents list(backtest and live trading) track record since publication. 10 | /// 11 | [Endpoint(Method.GET, "alpha/{id}/orders")] 12 | public class GetAlphaOrdersRequest : AttributeRequest> 13 | { 14 | /// 15 | /// Unique id hash of an Alpha published to the marketplace. 16 | /// 17 | [PathParameter("id")] 18 | public string Id { get; set; } 19 | 20 | /// 21 | /// Starting position for the search query. With very large datasets the results can be paginated and fetched in chunks starting from start. 22 | /// 23 | [QueryParameter("start")] 24 | public int Start { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAlphaTagsRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | using System.Collections.Generic; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Fetch number of alphas containing each tag 10 | /// 11 | [Endpoint(Method.GET, "alpha/tags/read")] 12 | public class GetAlphaTagsRequest : AttributeRequest> 13 | { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/GetAuthorByIdRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Fetch Author information by id to form models based around people. 9 | /// 10 | [Endpoint(Method.GET, "alpha/author/{id}")] 11 | public class GetAuthorByIdRequest : AttributeRequest 12 | { 13 | /// 14 | /// Unique id hash of an Author. 15 | /// 16 | [PathParameter("id")] 17 | public string Id { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/RemoveAlphaBidRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | 5 | namespace QuantConnect.AlphaStream.Requests 6 | { 7 | /// 8 | /// Request used to remove an bid for an alpha 9 | /// 10 | [Endpoint(Method.GET, "alpha/{id}/prices/bids/delete")] 11 | public class RemoveAlphaBidRequest : AttributeRequest 12 | { 13 | /// 14 | /// Unique id hash of an Alpha published to the marketplace. 15 | /// 16 | [PathParameter("id")] 17 | public string Id { get; set; } 18 | 19 | /// 20 | /// Unique id of an Bid made to the Alpha. 21 | /// 22 | [QueryParameter("bid-id")] 23 | public int BidId { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/RemoveAlphaStreamRequest.cs: -------------------------------------------------------------------------------- 1 | namespace QuantConnect.AlphaStream.Requests 2 | { 3 | /// 4 | /// Request used to remove an alpha being streamed 5 | /// 6 | public class RemoveAlphaStreamRequest 7 | { 8 | /// 9 | /// The alpha id stream to remove 10 | /// 11 | public string AlphaId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/RemoveInsightsStreamRequest.cs: -------------------------------------------------------------------------------- 1 | namespace QuantConnect.AlphaStream.Requests 2 | { 3 | /// 4 | /// Request used to remove an alpha being streamed 5 | /// 6 | /// Kept for backwards compatibility 7 | public class RemoveInsightsStreamRequest : RemoveAlphaStreamRequest 8 | { 9 | } 10 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/SearchAlphasRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using QuantConnect.AlphaStream.Infrastructure; 3 | using QuantConnect.AlphaStream.Models; 4 | using RestSharp; 5 | 6 | namespace QuantConnect.AlphaStream.Requests 7 | { 8 | /// 9 | /// Search endpoint for locating Alphas matching search criteria. All input values are optional and are joined with a logical AND for the filtered results. 10 | /// 11 | [Endpoint(Method.GET, "alpha/search")] 12 | public class SearchAlphasRequest : AttributeRequest> 13 | { 14 | /// 15 | /// Search for Alphas which have a specific accuracy range. 16 | /// 17 | [QueryParameter("accuracy")] 18 | public NumberRange Accuracy { get; set; } 19 | 20 | /// 21 | /// Array of asset classes to search. 22 | /// 23 | [QueryParameter("asset-classes")] 24 | public List AssetClasses { get; set; } = new List(); 25 | 26 | /// 27 | /// Hash Author identifier to locate. 28 | /// 29 | [QueryParameter("author")] 30 | public string Author { get; set; } 31 | 32 | /// 33 | /// Search for Alphas which utilize specific symbols. QuantConnect symbol identifier code. 34 | /// 35 | [QueryParameter("symbols")] 36 | public List Symbols { get; set; } = new List(); 37 | 38 | /// 39 | /// Search for Alphas which have a specific sharpe ratio range. 40 | /// 41 | [QueryParameter("sharpe")] 42 | public NumberRange Sharpe { get; set; } 43 | 44 | /// 45 | /// Search for Alphas which fall into a specific uniqueness range relative to existing portfolio. 46 | /// 47 | [QueryParameter("uniqueness")] 48 | public NumberRange Uniqueness { get; set; } 49 | 50 | /// 51 | /// The start index of the search. This is used to support pagination 52 | /// 53 | [QueryParameter("start")] 54 | public int Start { get; set; } 55 | 56 | /// 57 | /// Search for Alphas which include specific tags 58 | /// 59 | [QueryParameter("include")] 60 | public List IncludedTags { get; set; } = new List(); 61 | 62 | /// 63 | /// Search for Alphas which exclude specific tags 64 | /// 65 | [QueryParameter("exclude")] 66 | public List ExcludedTags { get; set; } = new List(); 67 | 68 | /// 69 | /// Search for Alphas with parameters in a specific range 70 | /// 71 | [QueryParameter("parameters")] 72 | public NumberRange Parameters { get; set; } = null; 73 | 74 | /// 75 | /// Search for alphas with an out-of-sample DTW distance in a specific range 76 | /// 77 | [QueryParameter("out-of-sample-dtw-distance")] 78 | public NumberRange DtwDistance { get; set; } 79 | 80 | /// 81 | /// Search for alphas with an out-of-sample returns correlation in a specific range 82 | /// 83 | [QueryParameter("out-of-sample-returns-correlation")] 84 | public NumberRange ReturnsCorrelation { get; set; } 85 | 86 | /// 87 | /// Search for alphas with a trial length in a specific range 88 | /// 89 | [QueryParameter("trial")] 90 | public NumberRange Trial { get; set; } 91 | } 92 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/Requests/SearchAuthorsRequest.cs: -------------------------------------------------------------------------------- 1 | using QuantConnect.AlphaStream.Infrastructure; 2 | using QuantConnect.AlphaStream.Models; 3 | using RestSharp; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace QuantConnect.AlphaStream.Requests 8 | { 9 | /// 10 | /// Search Author database by query filters to locate researchers according to criteria. 11 | /// 12 | [Endpoint(Method.GET, "alpha/author/search")] 13 | public class SearchAuthorsRequest : AttributeRequest> 14 | { 15 | /// 16 | /// Best guess geographic location of the Author based on the IP address. 17 | /// 18 | [QueryParameter("location")] 19 | public string Location { get; set; } 20 | 21 | /// 22 | /// Preferred programming language for the primary Author. 23 | /// 24 | [QueryParameter("languages")] 25 | public List Languages { get; set; } = new List(); 26 | 27 | /// 28 | /// Search the Author biography information for this text. 29 | /// 30 | [QueryParameter("biography")] 31 | public string Biography { get; set; } 32 | 33 | /// 34 | /// Number of Alphas the Author has listed. 35 | /// 36 | [QueryParameter("alphas")] 37 | public NumberRange AlphasListed { get; set; } 38 | 39 | /// 40 | /// Unix timestamp of the Author registration on QuantConnect. 41 | /// 42 | [QueryParameter("signed-up")] 43 | public DateRange SignedUp { get; set; } 44 | 45 | /// 46 | /// Unix timestamp of the Author last login on QuantConnect. 47 | /// 48 | [QueryParameter("last-login")] 49 | public DateRange LastLogin { get; set; } 50 | 51 | /// 52 | /// Number of discussions started on QuantConnect. 53 | /// 54 | [QueryParameter("forum-discussions")] 55 | public NumberRange ForumDiscussions { get; set; } 56 | 57 | /// 58 | /// Number of comments created on QuantConnect. 59 | /// 60 | [QueryParameter("forum-comments")] 61 | public NumberRange ForumComments { get; set; } 62 | 63 | /// 64 | /// Range of the number of projects. 65 | /// 66 | [QueryParameter("projects")] 67 | public NumberRange Projects { get; set; } 68 | 69 | /// 70 | /// The start index of the search. This is used to support pagination 71 | /// 72 | [QueryParameter("start")] 73 | public int Start { get; set; } 74 | } 75 | } -------------------------------------------------------------------------------- /QuantConnect.AlphaStream/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /QuantConnect.AlphaStreamsRunnerAlgorithm/Python/BrokerageSupportedSecurities.py: -------------------------------------------------------------------------------- 1 | from clr import AddReference 2 | AddReference("QuantConnect.Algorithm") 3 | AddReference("QuantConnect.Common") 4 | 5 | from QuantConnect import * 6 | from QuantConnect.Brokerages import * 7 | from QuantConnect.Data.Market import * 8 | 9 | BrokerageSupportedSecurities = { 10 | "AlpacaBrokerageModel": [SecurityType.Equity], 11 | "AlphaStreamsBrokerageModel": [SecurityType.Equity, SecurityType.Forex, SecurityType.Crypto, SecurityType.Future, SecurityType.Option, SecurityType.Cfd, SecurityType.Base], 12 | "BitfinexBrokerageModel": [SecurityType.Crypto], 13 | "DefaultBrokerageModel": [SecurityType.Equity, SecurityType.Forex, SecurityType.Crypto, SecurityType.Future, SecurityType.Option, SecurityType.Cfd, SecurityType.Base], 14 | "FxcmBrokerageModel": [SecurityType.Forex, SecurityType.Cfd], 15 | "GDAXBrokerageModel": [SecurityType.Crypto], 16 | "InteractiveBrokersBrokerageModel": [SecurityType.Equity, SecurityType.Forex, SecurityType.Future, SecurityType.Option], 17 | "OandaBrokerageModel": [SecurityType.Forex, SecurityType.Cfd], 18 | "TradierBrokerageModel": [SecurityType.Equity] 19 | } 20 | 21 | def BrokerageErrorMessage(symbol, brokerage): 22 | ErrorMessage = { 23 | "AlpacaBrokerageModel": f"Alpaca Brokerage doesn't support trading {symbol.Value}.", 24 | "AlphaStreamsBrokerageModel": f"Alpha Streams Brokerage doesn't support data for {symbol.Value}.", 25 | "BitfinexBrokerageModel": f"Bitfinex Brokerage doesn't support trading {symbol.Value}.", 26 | "DefaultBrokerageModel": f"Default Brokerage doesn't support data for {symbol.Value}.", 27 | "FxcmBrokerageModel": f"FXCM Brokerage doesn't support trading {symbol.Value}.", 28 | "GDAXBrokerageModel": f"GDAX Brokerage doesn't support trading {symbol.Value}.", 29 | "InteractiveBrokersBrokerageModel": f"Interactive Brokers doesn't support trading {symbol.Value}.", 30 | "OandaBrokerageModel": f"Oanda Brokerage doesn't support trading {symbol.Value}.", 31 | "TradierBrokerageModel": f"Tradier Brokerage doesn't support trading {symbol.Value}." 32 | } 33 | 34 | return ErrorMessage[brokerage] -------------------------------------------------------------------------------- /QuantConnect.AlphaStreamsRunnerAlgorithm/Python/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuantConnect/AlphaStreams/107e4be4df39f811a60659297a13f266fb9c6277/QuantConnect.AlphaStreamsRunnerAlgorithm/Python/__init__.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Alpha Streams SDK and Research](http://cdn.quantconnect.com.s3.us-east-1.amazonaws.com/i/github/alpha-streams-sdk.png) 2 | # QuantConnect Alpha Streams API SDK 3 | 4 | Welcome to the Alpha Streams API SDK Repository. Here we publish SDK implementations and research for connecting to the Alpha Streams Library and performing batch analysis on crowd-sourced strategies from the QuantConnect community. 5 | 6 | To sign up to the API go to QuantConnect.com/pricing and select the Alpha Stream API add-on from the pricing menu. This data is also available exported daily to a S3 bucket for file-based analysis. 7 | 8 | ## Available SDK Languages 9 | 10 | Currently there are two SDK implementations; Python and C#. Both are connecting to the same REST API backend. If you are an QuantConnect API client and would like us to publish an SDK in another language please let us know at support@quantconnect.com 11 | 12 | ### Python SDK Implementation: 13 | The python implementation of the SDK wrapper comes with two research notebooks for performing portfolio analysis([1](https://github.com/QuantConnect/AlphaStream/blob/master/AlphaStream/QuantConnect.AlphaStream.CompositeAlphaAnalysis.ipynb), [2](https://github.com/QuantConnect/AlphaStream/blob/master/AlphaStream/QuantConnect.AlphaStream.AlphaAnalysisNotebook.ipynb)), along with one-["kitchen sink" Jupyter Notebook](https://github.com/QuantConnect/AlphaStream/blob/master/AlphaStream/QuantConnectAlphaStreamsNotebook.ipynb) implementation. 14 | 15 | ### C# SDK Implementations: 16 | 17 | You can browse the [API implementation](https://github.com/QuantConnect/AlphaStream/tree/master/QuantConnect.AlphaStream), and also a full [demonstration](https://github.com/QuantConnect/AlphaStream/tree/master/QuantConnect.AlphaStream.Demo) of the API and querying it with the C# wrapper. 18 | 19 | ## Installation Instructions 20 | 21 | To install locally, download the zip file with the [latest master](https://github.com/QuantConnect/AlphaStream/archive/master.zip) and unzip it to your favorite location. Alternatively, install [Git](https://git-scm.com/downloads) and clone the repo: 22 | 23 | ``` 24 | git clone https://github.com/QuantConnect/AlphaStream.git 25 | ``` 26 | 27 | This solution depends on [QuantConnect/Lean](https://github.com/QuantConnect/). Consequently, we need to download the zip file with the [latest master](https://github.com/QuantConnect/Lean/archive/master.zip) and unzip it to same location. Alternatively, install [Git](https://git-scm.com/downloads) and clone the repo: 28 | 29 | ``` 30 | git clone https://github.com/QuantConnect/Lean.git 31 | ``` 32 | 33 | ## License Agreement 34 | 35 | This code is provided only for use with the Alpha Streams Repository and is not available for other commercial use beyond this purpose. It may not be copied, modified or distributed. All intellectual property remains with QuantConnect Corporation. -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Learn more: https://github.com/QuantConnect/AlphaStream/setup.py 3 | import os 4 | from setuptools import setup 5 | from codecs import open 6 | 7 | here = os.path.abspath(os.path.dirname(__file__)) 8 | os.chdir(here) 9 | 10 | packages = ['AlphaStream','AlphaStream.Models','AlphaStream.Requests','AlphaStream.QuantConnect'] 11 | 12 | requires = ['matplotlib>=3.0.2', 'pandas>=0.23.4', 'pika>=0.13.0', 'requests>=2.18.4'] 13 | 14 | about = {} 15 | with open(os.path.join(here, 'AlphaStream', '__version__.py'), 'r', 'utf-8') as f: 16 | exec(f.read(), about) 17 | 18 | with open('README.md', 'r', 'utf-8') as f: 19 | readme = f.read() 20 | 21 | setup( 22 | name=about['__title__'], 23 | version=about['__version__'], 24 | description=about['__description__'], 25 | long_description=readme, 26 | long_description_content_type='text/markdown', 27 | author=about['__author__'], 28 | author_email=about['__author_email__'], 29 | url=about['__url__'], 30 | packages=packages, 31 | include_package_data=True, 32 | python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", 33 | install_requires=requires, 34 | license=about['__license__'], 35 | zip_safe=False, 36 | classifiers=[ 37 | 'Development Status :: 5 - Production/Stable', 38 | 'Intended Audience :: Developers', 39 | 'Natural Language :: English', 40 | 'License :: OSI Approved :: Apache Software License', 41 | 'Programming Language :: Python', 42 | 'Programming Language :: Python :: 2', 43 | 'Programming Language :: Python :: 2.7', 44 | 'Programming Language :: Python :: 3', 45 | 'Programming Language :: Python :: 3.4', 46 | 'Programming Language :: Python :: 3.5', 47 | 'Programming Language :: Python :: 3.6', 48 | 'Programming Language :: Python :: 3.7', 49 | 'Programming Language :: Python :: Implementation :: CPython', 50 | 'Programming Language :: Python :: Implementation :: PyPy' 51 | ], 52 | ) 53 | --------------------------------------------------------------------------------