-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGet-YFStockQuote.ps1
118 lines (98 loc) · 5.26 KB
/
Get-YFStockQuote.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
function Get-YFStockQuote {
# Author: Daniel Ferreira (@daniel0x00)
# License: 0BSD
<#
.SYNOPSIS
Downloads delayed Yahoo Finance Stock Market Quote data. Very basic and non-polished cmdlet.
.EXAMPLE
# Bitcoin-USD, 1d candles, -1year lookback.
Get-YFStockQuote -Symbol BTC-USD -Range 1y
.EXAMPLE
# S&P-500 ETF, 5m candles, -1month lookback.
Get-YFStockQuote -Symbol SPY -Interval 5m -Range 1mo
.EXAMPLE
# Apple stock, 2m candles, -40days from today lookback.
Get-YFStockQuote -Symbol AAPL -Interval 2m -FromDate -40
.OUTPUTS
timestamp : 1606833000
symbol : SPY
interval : 5m
open : 365.6
high : 365.62
low : 364.93
close : 365.11
volume : 3052904
timestamp : 1606833300
symbol : SPY
interval : 5m
open : 365.06
high : 365.77
low : 364.93
close : 365.68
volume : 944011
#>
[CmdletBinding(DefaultParameterSetName='ByRange')]
[OutputType([PSCustomObject])]
param(
[Parameter(Position=0, Mandatory=$false, ValueFromPipeline=$true)]
[string] $Symbol='SPY',
# Candle size. '30m' is banned as it returns 60m candles. Possible TODO to anybody else to fix.
[Parameter(Mandatory=$false, ValueFromPipeline=$false)]
[ValidateSet("1m","2m","5m","15m","60m","90m","1h","1d","5d","1wk","1mo","3mo")]
[string] $Interval='1d',
# How far back it goes:
[Parameter(Mandatory=$false, ValueFromPipeline=$false, ParameterSetName='ByRange')]
[ValidateSet("1d","5d","1mo","3mo","6mo","1y","2y","5y","10y","ytd","max")]
[string] $Range='5d',
# How far back it goes, by date. Default is -30d:
[Parameter(Mandatory=$false, ValueFromPipeline=$false, ParameterSetName='ByDate')]
[int] $FromDate=([int](New-TimeSpan -Start (Get-Date '01/01/1970') -End (Get-Date).AddDays(-30).ToLocalTime()).TotalSeconds),
# Till how far back it goes, by date. Default is current day:
[Parameter(Mandatory=$false, ValueFromPipeline=$false, ParameterSetName='ByDate')]
[int] $ToDate=([int](New-TimeSpan -Start (Get-Date '01/01/1970') -End (Get-Date).AddDays(0).ToLocalTime()).TotalSeconds),
# Switch to skip candle size output.
# By default is $false, thereby will be shown.
# 'Interval' field is useful when all intervals are ingested as single file in a data warehouse platform.
[Parameter(Mandatory=$false, ValueFromPipeline=$false)]
[switch] $SkipIntervalOutput,
# Yahoo Finance base URL:
[Parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string] $UrlBase='https://query1.finance.yahoo.com/v8/finance/chart/'
)
switch ($PsCmdlet.ParameterSetName) {
"ByRange" { $Url = [string]::concat($UrlBase, ("{0}?region=US&lang=en-US&includePrePost=false&interval={1}&range={2}&corsDomain=finance.yahoo.com&.tsrc=finance" -f $Symbol,$Interval,$Range) ) }
"ByDate" {
# Received relative days:
if ($FromDate -lt 0) { $FromDate = ([int](New-TimeSpan -Start (Get-Date '01/01/1970') -End (Get-Date).AddDays($FromDate).ToLocalTime()).TotalSeconds) }
if ($ToDate -le 0) { $ToDate = ([int](New-TimeSpan -Start (Get-Date '01/01/1970') -End (Get-Date).AddDays($ToDate).ToLocalTime()).TotalSeconds) }
$Url = [string]::concat($UrlBase, ("{0}?region=US&lang=en-US&includePrePost=false&interval={1}&period1={2}&period2={3}&corsDomain=finance.yahoo.com&.tsrc=finance" -f $Symbol,$Interval,$FromDate,$ToDate) )
}
}
Write-Verbose "[Get-YFStockQuote] Downloading $Symbol quotes from URL: $Url..."
# Request builder:
$WebRequestParameters = @{
Uri = $Url
Method = 'Get'
Headers = @{
"Accept"="*/*"
"User-Agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}
}
$WebRequest = Invoke-RestMethod @WebRequestParameters -ErrorAction Stop
# Output:
if ($null -ne $WebRequest) {
$Output = 1..($WebRequest.chart.result[0].timestamp.count) | Select-Object `
@{n='timestamp';e={ $WebRequest.chart.result[0].timestamp[($_-1)] }}, `
@{n='symbol';e={ $Symbol }}, `
@{n='interval';e={ $Interval }}, `
@{n='open';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.quote[0].open[($_-1)],2) }}, `
@{n='high';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.quote[0].high[($_-1)],2) }}, `
@{n='low';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.quote[0].low[($_-1)],2) }}, `
@{n='close';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.quote[0].close[($_-1)],2) }}, `
#@{n='adjclose';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.adjclose[0].adjclose[($_-1)],2) }}, `
@{n='volume';e={ [System.Math]::Round($WebRequest.chart.result[0].indicators.quote[0].volume[($_-1)],2) }}
# Output:
if ($SkipIntervalOutput) { $Output | Select-Object -ExcludeProperty interval }
else { $Output }
}
}