Skip to content

Commit

Permalink
add support for options chain snapshot (#64)
Browse files Browse the repository at this point in the history
also fix incorrect type inference for some list APIs
  • Loading branch information
mmoghaddam385 authored Jan 4, 2023
1 parent 231f437 commit 9c9b760
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.polygon.kotlin.sdk.sample

import com.tylerthrailkill.helpers.prettyprint.pp
import io.ktor.client.plugins.*
import io.polygon.kotlin.sdk.rest.ComparisonQueryFilterParameters
import io.polygon.kotlin.sdk.DefaultOkHttpClientProvider
import io.polygon.kotlin.sdk.HttpClientProvider
import io.polygon.kotlin.sdk.rest.*
Expand All @@ -12,6 +11,7 @@ import io.polygon.kotlin.sdk.rest.experimental.ExperimentalAPI
import io.polygon.kotlin.sdk.rest.experimental.FinancialsParameters
import io.polygon.kotlin.sdk.rest.forex.HistoricTicksParameters
import io.polygon.kotlin.sdk.rest.forex.RealTimeConversionParameters
import io.polygon.kotlin.sdk.rest.options.SnapshotChainParameters
import io.polygon.kotlin.sdk.rest.reference.*
import io.polygon.kotlin.sdk.rest.stocks.GainersOrLosersDirection
import io.polygon.kotlin.sdk.rest.stocks.HistoricQuotesParameters
Expand Down Expand Up @@ -141,12 +141,25 @@ fun supportedTickersSample(polygonClient: PolygonRestClient) {

fun optionsContractsSample(polygonClient: PolygonRestClient) {
println("O:EVRI240119C00002500 contract details:")
polygonClient.referenceClient.getOptionsContractDetailsBlocking("O:EVRI240119C00002500", OptionsContractDetailsParameters()).pp()
polygonClient.referenceClient.getOptionsContractDetailsBlocking(
"O:EVRI240119C00002500",
OptionsContractDetailsParameters()
).pp()

println("AAPL contracts:")
polygonClient.referenceClient
.getOptionsContractsBlocking(OptionsContractsParameters(underlyingTicker = ComparisonQueryFilterParameters.equal("AAPL")))
.getOptionsContractsBlocking(
OptionsContractsParameters(
underlyingTicker = ComparisonQueryFilterParameters.equal(
"AAPL"
)
)
)
.pp()

println("list contracts: ")
polygonClient.referenceClient.listOptionsContracts(OptionsContractsParameters(limit = 5))
.asSequence().take(5).forEach { println("got an options contract: ${it.ticker}") }
}

fun tickerTypesSample(polygonClient: PolygonRestClient) {
Expand All @@ -163,13 +176,21 @@ fun tickerNewsSample(polygonClient: PolygonRestClient) {
println("Redfin news:")
val params = TickerNewsParametersV2(ticker = ComparisonQueryFilterParameters.equal("RDFN"), limit = 2)
polygonClient.referenceClient.getTickerNewsBlockingV2(params).pp()

println("list news:")
polygonClient.referenceClient.listTickerNewsV2(params)
.asSequence().take(10).forEach { println("news article: ${it.articleUrl}") }
}

fun splitsSample(polygonClient: PolygonRestClient) {
println("Apple splits:")
polygonClient.referenceClient
.getSplitsBlocking(SplitsParameters(ticker = ComparisonQueryFilterParameters.equal("AAPL")))
.pp()

println("list recent splits:")
polygonClient.referenceClient.listSplits(SplitsParameters(limit = 5))
.asSequence().take(15).forEach { println("split from ${it.executionDate}") }
}


Expand All @@ -189,13 +210,21 @@ fun dividendsSample(polygonClient: PolygonRestClient) {
limit = 1,
)
).pp()

println("15 most recent dividends")
polygonClient.referenceClient.listDividends(DividendsParameters(limit = 5))
.asSequence().take(15).forEach { println("got a dividend from ${it.exDividendDate}") }
}

@OptIn(ExperimentalAPI::class)
fun financialsSample(polygonClient: PolygonRestClient) {
println("RDFN financials")

@OptIn(ExperimentalAPI::class)
polygonClient.experimentalClient.getFinancialsBlocking(FinancialsParameters(ticker = "RDFN")).pp()
polygonClient.experimentalClient.listFinancials(FinancialsParameters(limit = 5))
.asSequence()
.take(15)
.forEach { println("got financials from ${it.sourceFilingURL}") }
}

fun marketStatusesSample(polygonClient: PolygonRestClient) {
Expand Down Expand Up @@ -243,6 +272,8 @@ fun dailyOpenCloseSample(polygonClient: PolygonRestClient) {
fun conditionsSample(polygonClient: PolygonRestClient) {
println("Conditions:")
polygonClient.referenceClient.getConditionsBlocking(ConditionsParameters()).pp()
polygonClient.referenceClient.listConditions(ConditionsParameters(limit = 5))
.asSequence().take(15).forEach { println("got condition #${it.id}") }
}

fun snapshotAllTickersSample(polygonClient: PolygonRestClient) {
Expand All @@ -265,6 +296,15 @@ fun optionsSnapshotSample(polygonClient: PolygonRestClient) {
polygonClient.optionsClient.getSnapshotBlocking("AAPL", "O:AAPL230616C00150000").pp()
}

fun optionsSnapshotChainSample(polygonClient: PolygonRestClient) {
print("RDFN options snapshots:")
polygonClient.optionsClient.getSnapshotChainBlocking("AAPL", SnapshotChainParameters()).pp()
polygonClient.optionsClient.listSnapshotChain("AA", SnapshotChainParameters(limit = 5))
.asSequence()
.take(15)
.forEach { println(it.details?.ticker ?: "UNKNOWN!") }
}

fun previousCloseSample(polygonClient: PolygonRestClient) {
println("RDFN Prev close:")
polygonClient.stocksClient.getPreviousCloseBlocking("RDFN", true).pp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
fun listFinancials(params: FinancialsParameters, vararg opts: PolygonRestOption): RequestIterator<Financials> =
RequestIterator(
{ getFinancialsBlocking(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<FinancialsResponse>(*opts)
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import io.polygon.kotlin.sdk.ext.coroutineToRestCallback
import io.polygon.kotlin.sdk.rest.PolygonRestApiCallback
import io.polygon.kotlin.sdk.rest.PolygonRestClient
import io.polygon.kotlin.sdk.rest.PolygonRestOption
import io.polygon.kotlin.sdk.rest.RequestIterator
import io.polygon.kotlin.sdk.rest.reference.PolygonReferenceClient
import kotlinx.coroutines.runBlocking
import javax.management.monitor.StringMonitor

/**
* Client for Polygon.io's Options pricing data RESTful APIs.
Expand Down Expand Up @@ -39,4 +41,43 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
) =
coroutineToRestCallback(callback, { getSnapshot(underlyingAsset, contract, *opts) })

/**
* Get the snapshot of all options contracts for an underlying ticker.
*
* API Doc: https://polygon.io/docs/options/get_v3_snapshot_options__underlyingasset___optioncontract
*/
@SafeVarargs
fun getSnapshotChainBlocking(
underlyingAsset: String,
params: SnapshotChainParameters,
vararg opts: PolygonRestOption
): SnapshotChainResponse =
runBlocking { getSnapshotChain(underlyingAsset, params, *opts) }

/** See [getSnapshotChainBlocking] */
@SafeVarargs
fun getSnapshotChain(
underlyingAsset: String,
params: SnapshotChainParameters,
callback: PolygonRestApiCallback<SnapshotChainResponse>,
vararg opts: PolygonRestOption
) =
coroutineToRestCallback(callback, { getSnapshotChain(underlyingAsset, params, *opts) })

/**
* Get an iterator to iterate through all pages of results for the given parameters.
*
* See [getSnapshotChainBlocking] if you instead need to get exactly one page of results.
* See section "Pagination" in the README for more details on iterators.
*/
@SafeVarargs
fun listSnapshotChain(
underlyingAsset: String,
params: SnapshotChainParameters,
vararg opts: PolygonRestOption
): RequestIterator<Snapshot> =
RequestIterator(
{ getSnapshotChainBlocking(underlyingAsset, params, *opts) },
polygonClient.requestIteratorFetch<SnapshotChainResponse>(*opts)
)
}
66 changes: 66 additions & 0 deletions src/main/kotlin/io/polygon/kotlin/sdk/rest/options/Snapshots.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,91 @@
package io.polygon.kotlin.sdk.rest.options

import com.thinkinglogic.builder.annotation.Builder
import io.ktor.http.*
import io.polygon.kotlin.sdk.rest.ComparisonQueryFilterParameters
import io.polygon.kotlin.sdk.rest.Paginatable
import io.polygon.kotlin.sdk.rest.PolygonRestOption
import io.polygon.kotlin.sdk.rest.applyComparisonQueryFilterParameters
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/** See [PolygonOptionsClient.getSnapshotBlocking] */
@SafeVarargs
suspend fun PolygonOptionsClient.getSnapshot(
underlyingAsset: String,
contract: String,
vararg opts: PolygonRestOption
): SnapshotResponse =
polygonClient.fetchResult({ path("v3", "snapshot", "options", underlyingAsset, contract) }, *opts)

@SafeVarargs
suspend fun PolygonOptionsClient.getSnapshotChain(
underlyingAsset: String,
params: SnapshotChainParameters,
vararg opts: PolygonRestOption
): SnapshotChainResponse =
polygonClient.fetchResult({
path("v3", "snapshot", "options", underlyingAsset)

applyComparisonQueryFilterParameters("strike_price", params.strikePrice)
applyComparisonQueryFilterParameters("expiration_date", params.expirationDate)
params.contractType?.let { parameters["contract_type"] = it }
params.order?.let { parameters["order"] = it }
params.limit?.let { parameters["limit"] = it.toString() }
params.sort?.let { parameters["sort"] = it }

}, *opts)

@Builder
data class SnapshotChainParameters(

/**
* Query by strike price of the contract.
*/
val strikePrice: ComparisonQueryFilterParameters<Double>? = null,

/**
* Query by expiration date of the contract with date format YYYY-MM-DD.
*/
val expirationDate: ComparisonQueryFilterParameters<String>? = null,

/**
* Query by the type of contract. 'call' or 'put'.
*/
val contractType: String? = null,

/**
* Order results based on the sort field.
* Can be "asc" or "desc"
*/
val order: String? = null,

/**
* Limit the number of results returned, default is 10 and max is 1000.
*/
val limit: Int? = null,

/**
* Field used for ordering. See docs for valid fields
*/
val sort: String? = null
)

@Serializable
data class SnapshotResponse(
val status: String? = null,
@SerialName("request_id") val requestId: String? = null,
val results: Snapshot? = null,
)

@Serializable
data class SnapshotChainResponse(
val status: String? = null,
@SerialName("request_id") val requestId: String? = null,
@SerialName("next_url") override val nextUrl: String? = null,
override val results: List<Snapshot> = emptyList()
) : Paginatable<Snapshot>

@Serializable
data class Snapshot(
@SerialName("break_even_price") val breakEvenPrice: Double? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
): RequestIterator<OptionsContract> =
RequestIterator(
{ getOptionsContractsBlocking(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<OptionsContractsResponse>(*opts)
)

/**
Expand Down Expand Up @@ -255,7 +255,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
fun listTickerNewsV2(params: TickerNewsParametersV2, vararg opts: PolygonRestOption): RequestIterator<TickerNews> =
RequestIterator(
{ getTickerNewsBlockingV2(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<TickerNewsResponse>(*opts)
)

/**
Expand Down Expand Up @@ -341,7 +341,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
fun listSplits(params: SplitsParameters, vararg opts: PolygonRestOption): RequestIterator<Split> =
RequestIterator(
{ getSplitsBlocking(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<SplitsResponse>(*opts)
)

/**
Expand Down Expand Up @@ -393,7 +393,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
fun listDividends(params: DividendsParameters, vararg opts: PolygonRestOption): RequestIterator<Dividend> =
RequestIterator(
{ getDividendsBlocking(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<DividendsResponse>(*opts)
)

/**
Expand Down Expand Up @@ -481,7 +481,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) {
fun listConditions(params: ConditionsParameters, vararg opts: PolygonRestOption): RequestIterator<Condition> =
RequestIterator(
{ getConditionsBlocking(params, *opts) },
polygonClient.requestIteratorFetch(*opts)
polygonClient.requestIteratorFetch<ConditionsResponse>(*opts)
)

/**
Expand Down

0 comments on commit 9c9b760

Please sign in to comment.