diff --git a/sample/src/main/java/io/polygon/kotlin/sdk/sample/KotlinUsageSample.kt b/sample/src/main/java/io/polygon/kotlin/sdk/sample/KotlinUsageSample.kt index cc36d96..53a4aef 100644 --- a/sample/src/main/java/io/polygon/kotlin/sdk/sample/KotlinUsageSample.kt +++ b/sample/src/main/java/io/polygon/kotlin/sdk/sample/KotlinUsageSample.kt @@ -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.* @@ -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 @@ -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) { @@ -163,6 +176,10 @@ 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) { @@ -170,6 +187,10 @@ fun splitsSample(polygonClient: PolygonRestClient) { 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}") } } @@ -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) { @@ -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) { @@ -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() diff --git a/src/main/kotlin/io/polygon/kotlin/sdk/rest/experimental/PolygonExperimentalClient.kt b/src/main/kotlin/io/polygon/kotlin/sdk/rest/experimental/PolygonExperimentalClient.kt index 54e0dbb..9ca6d30 100644 --- a/src/main/kotlin/io/polygon/kotlin/sdk/rest/experimental/PolygonExperimentalClient.kt +++ b/src/main/kotlin/io/polygon/kotlin/sdk/rest/experimental/PolygonExperimentalClient.kt @@ -48,7 +48,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { fun listFinancials(params: FinancialsParameters, vararg opts: PolygonRestOption): RequestIterator = RequestIterator( { getFinancialsBlocking(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) } diff --git a/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/PolygonOptionsClient.kt b/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/PolygonOptionsClient.kt index c43d1b3..effc2d6 100644 --- a/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/PolygonOptionsClient.kt +++ b/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/PolygonOptionsClient.kt @@ -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. @@ -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, + 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 = + RequestIterator( + { getSnapshotChainBlocking(underlyingAsset, params, *opts) }, + polygonClient.requestIteratorFetch(*opts) + ) } diff --git a/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/Snapshots.kt b/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/Snapshots.kt index 24255d8..74ce808 100644 --- a/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/Snapshots.kt +++ b/src/main/kotlin/io/polygon/kotlin/sdk/rest/options/Snapshots.kt @@ -1,11 +1,16 @@ 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, @@ -13,6 +18,59 @@ suspend fun PolygonOptionsClient.getSnapshot( ): 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? = null, + + /** + * Query by expiration date of the contract with date format YYYY-MM-DD. + */ + val expirationDate: ComparisonQueryFilterParameters? = 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, @@ -20,6 +78,14 @@ data class SnapshotResponse( 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 = emptyList() +) : Paginatable + @Serializable data class Snapshot( @SerialName("break_even_price") val breakEvenPrice: Double? = null, diff --git a/src/main/kotlin/io/polygon/kotlin/sdk/rest/reference/PolygonReferenceClient.kt b/src/main/kotlin/io/polygon/kotlin/sdk/rest/reference/PolygonReferenceClient.kt index 63485e2..f863cfb 100644 --- a/src/main/kotlin/io/polygon/kotlin/sdk/rest/reference/PolygonReferenceClient.kt +++ b/src/main/kotlin/io/polygon/kotlin/sdk/rest/reference/PolygonReferenceClient.kt @@ -105,7 +105,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { ): RequestIterator = RequestIterator( { getOptionsContractsBlocking(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) /** @@ -255,7 +255,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { fun listTickerNewsV2(params: TickerNewsParametersV2, vararg opts: PolygonRestOption): RequestIterator = RequestIterator( { getTickerNewsBlockingV2(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) /** @@ -341,7 +341,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { fun listSplits(params: SplitsParameters, vararg opts: PolygonRestOption): RequestIterator = RequestIterator( { getSplitsBlocking(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) /** @@ -393,7 +393,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { fun listDividends(params: DividendsParameters, vararg opts: PolygonRestOption): RequestIterator = RequestIterator( { getDividendsBlocking(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) /** @@ -481,7 +481,7 @@ internal constructor(internal val polygonClient: PolygonRestClient) { fun listConditions(params: ConditionsParameters, vararg opts: PolygonRestOption): RequestIterator = RequestIterator( { getConditionsBlocking(params, *opts) }, - polygonClient.requestIteratorFetch(*opts) + polygonClient.requestIteratorFetch(*opts) ) /**