Header menu logo Teaching

BinderScriptNotebook Group Name:

Student Name

Student Number

1:

2:

3:

4:

5:

This is an assignment. You should work in groups. Please write your group and group member names above. You will find sections labeled Task asking you to do each piece of analysis. Please make sure that you complete all of these tasks. I included some tests to help you see if you are calculating the solution correctly, but if you cannot get the test to pass submit your best attempt and you may recieve partial credit.

All work that you submit should be your own. Make use of the course resources and example code on the course website. It should be possible to complete all the requested tasks using information given below or somewhere on the course website.

For testing

#r "nuget: FsUnit.Xunit"
#r "nuget: xunit, 2.*"
open Xunit
open FsUnit.Xunit
open FsUnitTyped

For the assignment

#r "nuget: FSharp.Data, 5.0.2"
#r "nuget: FSharp.Stats, 0.5.0"
#r "nuget: NovaSBE.Finance, 0.5.0"
#r "nuget: MathNet.Numerics"
#r "nuget: MathNet.Numerics.FSharp"
#r "nuget: Plotly.NET, 3.*"
open System
open FSharp.Data
open Plotly.NET
open FSharp.Stats
open MathNet.Numerics.Statistics
open NovaSBE.Finance.Ols

Load Data

First, make sure that you're referencing the correct files.

Here I'm assuming that you have a class folder with this notebook and a data folder inside of it. The folder hierarchy would look like below where you have the below files and folders accessible:

/class
    notebook.ipynb
    id_and_return_data.csv
    rd_sale.csv
    
open NovaSBE.Finance.Portfolio

Data files

We assume the id_and_return_data.csv file and the signal csv file are in the notebook folder.

let [<Literal>] IdAndReturnsFilePath = "id_and_return_data.csv"
let [<Literal>] MySignalFilePath = "rd_sale.csv"
let strategyName = "R&D to sales"

If my paths are correct, then this code should read the first few lines of the files. If it doesn't show the first few lines, fix the above file paths.

IO.File.ReadLines(IdAndReturnsFilePath) 
|> Seq.truncate 5
|> Seq.iter (printfn "%A")
IO.File.ReadLines(MySignalFilePath) 
|> Seq.truncate 5
|> Seq.iter (printfn "%A")

Ok, now assuming those paths were correct the below code will work. I will put all this prep code in one block so that it is easy to run.

let idAndReturnsCsv = 
    CsvProvider<IdAndReturnsFilePath,ResolutionFolder = __SOURCE_DIRECTORY__>.GetSample().Rows 
    |> Seq.toList
let mySignalCsv = 
    CsvProvider<MySignalFilePath,ResolutionFolder = __SOURCE_DIRECTORY__>.GetSample().Rows 
    |> Seq.toList

A list of Signal records. The signal type is defined in the NovaSBE.Finance.Portfolio module here.

let mySignals =
    mySignalCsv
    |> List.choose (fun row -> 
        match row.Signal with
        | None -> None
        | Some signal ->
            let signalRecord: Signal =
                { SecurityId = Other row.Id
                  FormationDate = DateTime(row.Eom.Year, row.Eom.Month, 1)
                  Signal = signal }
            Some signalRecord)

// look at a few signals
mySignals[..3]

A list of Security return records. The SecurityReturn type is defined in the NovaSBE.Finance.Portfolio module here

let myReturns =
    idAndReturnsCsv
    |> List.choose (fun row -> 
        match row.Ret with
        | None -> None
        | Some ret ->
            let ret: SecurityReturn =
                { SecurityId = Other row.Id
                  Date = DateTime(row.Eom.Year, row.Eom.Month, 1)
                  Return= ret }
            Some ret)

// look at a few returns
myReturns[..3]

A list of security market caps. We'll need this for value-weight portfolios. The WeightVariable type is defined in the NovaSBE.Finance.Portfolio module here.

let myMktCaps =
    idAndReturnsCsv
    |> List.choose (fun row -> 
        match row.MarketEquity with
        | None -> None
        | Some mktCap ->
            let mktCap: WeightVariable =
                { SecurityId = Other row.Id
                  FormationDate = DateTime(row.Eom.Year, row.Eom.Month, 1)
                  Value = mktCap }
            Some mktCap)

// look at a few market caps
myMktCaps[..3]

Forming our strategy

We're now going to use the Backtest code to generate portfolios. It is defined in the NovaSBE.Finance.Portfolio module here. The Backtest class automates some of the code we did earlier to make portfolio construction simpler.

let backtest = Backtest(returns=myReturns, signals=mySignals, nPortfolios=3, name = strategyName)

Value Weighted Portfolios

let vw = backtest.strategyValueWeighted(myMktCaps)

vw.Portfolios[..3]
vw.Returns[..3]

Long-short portfolios

We get the Fama-French 3-Factor asset pricing model data.

open NovaSBE.Finance

let ff3Lookup = 
    French.getFF3 French.Frequency.Monthly
    |> Array.map (fun x -> DateTime(x.Date.Year, x.Date.Month, 1), x)
    |> Map

Isolate some notable portfolios.

type SignalPortfolioObs = 
    { Month: DateTime
      Name: string
      ExcessReturn: float }
let long =
    vw.Returns
    |> List.filter (fun row -> row.Index = 3)
    |> List.map (fun row ->
        let retx = row.Return - ff3Lookup[row.Month].Rf 
        { Month = row.Month
          Name = "Long"
          ExcessReturn = retx })

let short =
    vw.Returns
    |> List.filter (fun row -> row.Index = 1)
    |> List.map (fun row -> 
        let retx = row.Return - ff3Lookup[row.Month].Rf 
        { Month = row.Month
          Name = "Short"
          ExcessReturn = retx })

let longShort =
    vw.Returns
    |> List.groupBy (fun x -> x.Month)
    |> List.map (fun (month, xs) ->
        let long = xs |> List.find (fun x -> x.Index = 3)
        let short = xs |> List.find (fun x -> x.Index = 1)
        { Month = long.Month
          Name = "Long-short"
          ExcessReturn = long.Return - short.Return })

Start of assignment

Task: Calculate the annualized Sharpe ratios of your long, short, and long-short portfolios. Assign them to values longSharpe, shortSharpe, and longShortSharpe, respectively.

// Solution here.

Tests

longSharpe |> should (equalWithin 1e-6) 0.2613490337
shortSharpe |> should (equalWithin 1e-6) 0.490118588
longShortSharpe |> should (equalWithin 1e-6) -0.05676492997

Task: Create a list<RegData> for your long-short portfolio. Assign it to a value named longShortRd.

type RegData =
    { Month: DateTime
      ExcessReturn: float 
      MktRf: float
      Hml: float
      Smb: float }

// Solution here.

Tests

longShortRd |> shouldHaveLength 252
longShortRd |> should be ofExactType<RegData list>

Task: Fit CAPM and Fama-French 3-factor models for your long-short portfolio. Assign them to a values named capmModel and ff3Model, respectively.

// Solution here.

Tests.

capmModel |> should be ofExactType<RegressionResults>
ff3Model |> should be ofExactType<RegressionResults>

CAPM model evaluation.

Task: What is the CAPM alpha for your long-short portfolio? Use code to assign the alpha to the value capmAlpha. Is it significantly different from zero? Use code to assign the t-statistic to the value capmAlphaT.

// Solution here.

Tests

capmAlpha |> should (equalWithin 1e-6) -0.003015844638
capmAlphT |> should (equalWithin 1e-6) -1.011538156

Task: What is the CAPM beta for your long-short portfolio? Use code to assign the beta to the value capmBeta. Is it significantly different from zero? Use code to assign the t-statistic to the value capmBetaT.

// Solution here.

Tests

capmBeta |> should (equalWithin 1e-6) 0.3874415756
capmBetaT |> should (equalWithin 1e-6) 5.957967542

Task: What is the information ratio for your long-short portfolio when using the CAPM model? Assign it to a value named capmIR.

// Solution here.

Tests

capmIR |> should (equalWithin 1e-6) -0.06434136117

Fama-French 3-factor model evaluation.

Task: What is the Fama-French 3-factor model alpha for your long-short portfolio. Is it significantly different from zero?

// Solution here.

Task: What are the betas on the Market, HML, and SMB factors for your long-short portfolio. Are they significantly different from zero?

// Solution here.

Task: Based on the Market, HML, and SMB factor betas for your long-short portfolio, would you say your portfolio is more like a value portfolio, more like a growth portfolio, or neither? Explain.

// Solution here.

Task: Based on the Market, HML, and SMB factor betas for your long-short portfolio, would you say your portfolio is more like a small-cap portfolio, more like a large-cap portfolio, or neither? Explain.

// Solution here.

Task: What is the information ratio for your long-short portfolio when using the Fama and French 3-factor model?

// Solution here.
namespace Xunit
namespace FsUnit
module Xunit from FsUnit
namespace FsUnitTyped
namespace System
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
namespace Plotly
namespace Plotly.NET
namespace FSharp.Stats
namespace MathNet
namespace MathNet.Numerics
namespace MathNet.Numerics.Statistics
namespace NovaSBE
namespace NovaSBE.Finance
module Ols from NovaSBE.Finance
module Portfolio from NovaSBE.Finance
Multiple items
type LiteralAttribute = inherit Attribute new: unit -> LiteralAttribute

--------------------
new: unit -> LiteralAttribute
[<Literal>] val IdAndReturnsFilePath: string = "id_and_return_data.csv"
[<Literal>] val MySignalFilePath: string = "rd_sale.csv"
val strategyName: string
namespace System.IO
type File = static member AppendAllLines: path: string * contents: IEnumerable<string> -> unit + 1 overload static member AppendAllLinesAsync: path: string * contents: IEnumerable<string> * encoding: Encoding * ?cancellationToken: CancellationToken -> Task + 1 overload static member AppendAllText: path: string * contents: string -> unit + 1 overload static member AppendAllTextAsync: path: string * contents: string * encoding: Encoding * ?cancellationToken: CancellationToken -> Task + 1 overload static member AppendText: path: string -> StreamWriter static member Copy: sourceFileName: string * destFileName: string -> unit + 1 overload static member Create: path: string -> FileStream + 2 overloads static member CreateSymbolicLink: path: string * pathToTarget: string -> FileSystemInfo static member CreateText: path: string -> StreamWriter static member Decrypt: path: string -> unit ...
<summary>Provides static methods for the creation, copying, deletion, moving, and opening of a single file, and aids in the creation of <see cref="T:System.IO.FileStream" /> objects.</summary>
IO.File.ReadLines(path: string) : Collections.Generic.IEnumerable<string>
IO.File.ReadLines(path: string, encoding: Text.Encoding) : Collections.Generic.IEnumerable<string>
Multiple items
module Seq from FSharp.Stats
<summary> Module to compute common statistical measure </summary>

--------------------
module Seq from Microsoft.FSharp.Collections

--------------------
type Seq = new: unit -> Seq static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float seq static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float seq

--------------------
new: unit -> Seq
val truncate: count: int -> source: 'T seq -> 'T seq
val iter: action: ('T -> unit) -> source: 'T seq -> unit
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val idAndReturnsCsv: CsvProvider<...>.Row list
type CsvProvider
<summary>Typed representation of a CSV file.</summary> <param name='Sample'>Location of a CSV sample file or a string containing a sample CSV document.</param> <param name='Separators'>Column delimiter(s). Defaults to <c>,</c>.</param> <param name='InferRows'>Number of rows to use for inference. Defaults to <c>1000</c>. If this is zero, all rows are used.</param> <param name='Schema'>Optional column types, in a comma separated list. Valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c>, <c>string</c>, <c>int?</c>, <c>int64?</c>, <c>bool?</c>, <c>float?</c>, <c>decimal?</c>, <c>date?</c>, <c>datetimeoffset?</c>, <c>timespan?</c>, <c>guid?</c>, <c>int option</c>, <c>int64 option</c>, <c>bool option</c>, <c>float option</c>, <c>decimal option</c>, <c>date option</c>, <c>datetimeoffset option</c>, <c>timespan option</c>, <c>guid option</c> and <c>string option</c>. You can also specify a unit and the name of the column like this: <c>Name (type&lt;unit&gt;)</c>, or you can override only the name. If you don't want to specify all the columns, you can reference the columns by name like this: <c>ColumnName=type</c>.</param> <param name='HasHeaders'>Whether the sample contains the names of the columns as its first line.</param> <param name='IgnoreErrors'>Whether to ignore rows that have the wrong number of columns or which can't be parsed using the inferred or specified schema. Otherwise an exception is thrown when these rows are encountered.</param> <param name='SkipRows'>Skips the first n rows of the CSV file.</param> <param name='AssumeMissingValues'>When set to true, the type provider will assume all columns can have missing values, even if in the provided sample all values are present. Defaults to false.</param> <param name='PreferOptionals'>When set to true, inference will prefer to use the option type instead of nullable types, <c>double.NaN</c> or <c>""</c> for missing values. Defaults to false.</param> <param name='Quote'>The quotation mark (for surrounding values containing the delimiter). Defaults to <c>"</c>.</param> <param name='MissingValues'>The set of strings recognized as missing values specified as a comma-separated string (e.g., "NA,N/A"). Defaults to <c>NaN,NA,N/A,#N/A,:,-,TBA,TBD</c>.</param> <param name='CacheRows'>Whether the rows should be caches so they can be iterated multiple times. Defaults to true. Disable for large datasets.</param> <param name='Culture'>The culture used for parsing numbers and dates. Defaults to the invariant culture.</param> <param name='Encoding'>The encoding used to read the sample. You can specify either the character set name or the codepage number. Defaults to UTF8 for files, and to ISO-8859-1 the for HTTP requests, unless <c>charset</c> is specified in the <c>Content-Type</c> response header.</param> <param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param> <param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource (e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
val toList: source: 'T seq -> 'T list
val mySignalCsv: CsvProvider<...>.Row list
val mySignals: Signal list
Multiple items
module List from FSharp.Stats
<summary> Module to compute common statistical measure on list </summary>

--------------------
module List from Microsoft.FSharp.Collections

--------------------
type List = new: unit -> List static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float list static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float list

--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T member IsEmpty: bool member Item: index: int -> 'T with get ...

--------------------
new: unit -> List
val choose: chooser: ('T -> 'U option) -> list: 'T list -> 'U list
val row: CsvProvider<...>.Row
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val signal: float
val signalRecord: Signal
Multiple items
namespace FSharp.Stats.Signal

--------------------
type Signal = { SecurityId: SecurityId FormationDate: DateTime Signal: float }
type SecurityId = | Ticker of string | Cusip of string | Bloomberg of string | Permno of int | Other of string
union case SecurityId.Other: string -> SecurityId
Multiple items
[<Struct>] type DateTime = new: year: int * month: int * day: int -> unit + 16 overloads member Add: value: TimeSpan -> DateTime member AddDays: value: float -> DateTime member AddHours: value: float -> DateTime member AddMicroseconds: value: float -> DateTime member AddMilliseconds: value: float -> DateTime member AddMinutes: value: float -> DateTime member AddMonths: months: int -> DateTime member AddSeconds: value: float -> DateTime member AddTicks: value: int64 -> DateTime ...
<summary>Represents an instant in time, typically expressed as a date and time of day.</summary>

--------------------
DateTime ()
   (+0 other overloads)
DateTime(ticks: int64) : DateTime
   (+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
   (+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
   (+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
   (+0 other overloads)
val myReturns: SecurityReturn list
val ret: float
val ret: SecurityReturn
type SecurityReturn = { SecurityId: SecurityId Date: DateTime Return: float }
val myMktCaps: WeightVariable list
val mktCap: float
val mktCap: WeightVariable
type WeightVariable = { SecurityId: SecurityId FormationDate: DateTime Value: float }
val backtest: Backtest
Multiple items
type Backtest = new: returns: SecurityReturn seq * signals: Signal seq * nPortfolios: int * ?name: string * ?inParallel: bool -> Backtest member strategyEqualWeighted: unit -> BackTestResult member strategyValueWeighted: marketCaps: WeightVariable seq -> BackTestResult
<summary>Constructs a backtest of a trading strategy based on signals.</summary>
<param name="returns">A sequence of security returns.</param>
<param name="signals">A sequence of signals for each security and formation date.</param>
<param name="nPortfolios">The number of cross-sectionally sorted portfolios to create.</param>
<param name="name">The name of the strategy.</param>
<param name="inParallel">Whether to run the backtest in parallel.</param>
<returns>The portfolio positions each formation date and the portfolio returns.</returns>


--------------------
new: returns: SecurityReturn seq * signals: Signal seq * nPortfolios: int * ?name: string * ?inParallel: bool -> Backtest
val vw: BackTestResult
member Backtest.strategyValueWeighted: marketCaps: WeightVariable seq -> BackTestResult
BackTestResult.Portfolios: Portfolio list
BackTestResult.Returns: PortfolioReturn list
val ff3Lookup: Map<DateTime,French.FF3Obs>
module French from NovaSBE.Finance
val getFF3: frequency: French.Frequency -> French.FF3Obs array
type Frequency = | Daily | Monthly
union case French.Frequency.Monthly: French.Frequency
Multiple items
type Array = new: unit -> Array static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float array static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float array

--------------------
new: unit -> Array
val map: mapping: ('T -> 'U) -> array: 'T array -> 'U array
val x: French.FF3Obs
French.FF3Obs.Date: DateTime
property DateTime.Year: int with get
<summary>Gets the year component of the date represented by this instance.</summary>
<returns>The year, between 1 and 9999.</returns>
property DateTime.Month: int with get
<summary>Gets the month component of the date represented by this instance.</summary>
<returns>The month component, expressed as a value between 1 and 12.</returns>
Multiple items
module Map from FSharp.Stats
<summary> Module to strore specialised computations on maps </summary>

--------------------
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
type SignalPortfolioObs = { Month: DateTime Name: string ExcessReturn: float }
Multiple items
val string: value: 'T -> string

--------------------
type string = String
Multiple items
val float: value: 'T -> float (requires member op_Explicit)

--------------------
type float = Double

--------------------
type float<'Measure> = float
val long: SignalPortfolioObs list
val filter: predicate: ('T -> bool) -> list: 'T list -> 'T list
val row: PortfolioReturn
PortfolioReturn.Index: int
val map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
val retx: float
PortfolioReturn.Return: float
PortfolioReturn.Month: DateTime
val short: SignalPortfolioObs list
val longShort: SignalPortfolioObs list
val groupBy: projection: ('T -> 'Key) -> list: 'T list -> ('Key * 'T list) list (requires equality)
val x: PortfolioReturn
val month: DateTime
val xs: PortfolioReturn list
val long: PortfolioReturn
val find: predicate: ('T -> bool) -> list: 'T list -> 'T
val short: PortfolioReturn
val sharpe: xs: float list -> float
val xs: float list
type 'T list = List<'T>
val mn: float
val average: list: 'T list -> 'T (requires member (+) and member DivideByInt and member Zero)
val sd: float
val stDev: items: 'T seq -> 'U (requires member (-) and member Zero and member DivideByInt and member (+) and member ( * ) and member (+) and member (/) and member Sqrt)
<summary> Computes the sample standard deviation </summary>
<param name="items">The input sequence.</param>
<remarks>Returns NaN if data is empty or if any entry is NaN.</remarks>
<returns>standard deviation of a sample (Bessel's correction by N-1)</returns>
val sqrt: value: 'T -> 'U (requires member Sqrt)
val longSharpe: float
val x: SignalPortfolioObs
SignalPortfolioObs.ExcessReturn: float
val shortSharpe: float
val longShortSharpe: float
val should: f: ('a -> #NHamcrest.IMatcher<obj>) -> x: 'a -> actual: obj -> unit
val equalWithin: tolerance: obj -> expected: obj -> NHamcrest.Core.CustomMatcher<obj>
type RegData = { Month: DateTime ExcessReturn: float MktRf: float Hml: float Smb: float }
val longShortRd: RegData list
SignalPortfolioObs.Month: DateTime
val shouldHaveLength: expected: int -> actual: 'a seq -> unit
val be: ('b -> 'b)
val ofExactType<'a> : NHamcrest.Core.CustomMatcher<obj>
val capmModel: RegressionResults
Multiple items
module Ols from NovaSBE.Finance

--------------------
type Ols<'Record> = new: formula: string * data: 'Record seq -> Ols<'Record> member fit: unit -> RegressionResults member df_model: int member df_resid: int member endog_names: string member exog_names: string array member k_constant: int
<summary>Create a model from a formula and collection of records</summary>

--------------------
new: formula: string * data: 'Record seq -> Ols<'Record>
val ff3Model: RegressionResults
Multiple items
type RegressionResults = new: df_model: int * df_resid: int * endog: float array * exog: float array array * endog_names: string * exog_names: string array * intercept: bool * covtype: CovType -> RegressionResults member predict: data: 'a seq -> float array member summary: ?yname: string * ?xname: string seq * ?title: string * ?alpha: float * ?slim: bool -> string member coefs: Map<string,float> member df_model: int member df_resid: int member endog_names: string member ess: float member exog_names: string array member f_pvalue: float ...

--------------------
new: df_model: int * df_resid: int * endog: float array * exog: float array array * endog_names: string * exog_names: string array * intercept: bool * covtype: CovType -> RegressionResults
val capmAlpha: float
property RegressionResults.coefs: Map<string,float> with get
<summary> The estimated model coefficients </summary>
val capmAlphT: float
property RegressionResults.tvalues: Map<string,float> with get
<summary> The t-statistics of the model coefficients </summary>
val capmBeta: float
val capmBetaT: float
val capmIR: float
property RegressionResults.resid: float array with get
<summary> The model residuals </summary>

Type something to start searching.