Skip to content

Commit

Permalink
Add support for Upstox API v2.0
Browse files Browse the repository at this point in the history
1. Add support for rate limits introduced by Upstox.
2. Introduced 'RetryPolicyFactory' to provide support for retries on failed API requests.
3. Add method for new API endpoint - Fetch Subscribed Symbols.
4. Add support for the new Historical endpoint.
5. WebSocket reconnect feature provided by the OkHTTP library is now disabled by default.
6. Updated Google Guava to '27.0.1-jre'.
7. Updated the tests.
  • Loading branch information
rishabh9 committed Dec 31, 2018
1 parent 18cdb50 commit a8fe6a4
Show file tree
Hide file tree
Showing 26 changed files with 1,014 additions and 263 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ demonstrating the usage of Riko. Feel free to use it as a starter for your own p
<dependency>
<groupId>com.github.rishabh9</groupId>
<artifactId>riko</artifactId>
<version>2.0.2-SNAPSHOT</version>
<version>3.0.0-SNAPSHOT</version>
</dependency>
```

### For Gradle based project
```groovy
dependencies {
implementation 'com.github.rishabh9:riko:2.0.2-SNAPSHOT'
implementation 'com.github.rishabh9:riko:3.0.0-SNAPSHOT'
}
```

### For SBT based project
```scala
libraryDependencies += "com.github.rishabh9" % "riko" % "2.0.2-SNAPSHOT"
libraryDependencies += "com.github.rishabh9" % "riko" % "3.0.0-SNAPSHOT"
```
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ dependencyManagement {
// GroupId
group = 'com.github.rishabh9'
// Version
version = '2.0.2-SNAPSHOT'
version = '3.0.0-SNAPSHOT'
archivesBaseName = 'riko'

dependencies {
Expand All @@ -56,7 +56,7 @@ dependencies {

// These dependencies are used internally, and not exposed to consumers on their own compile classpath.
// Developer's toolkit
implementation 'com.google.guava:guava:23.0'
implementation 'com.google.guava:guava:27.0.1-jre'
implementation 'net.jodah:failsafe:1.1.1'
// Making API calls
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* MIT License
*
* Copyright (c) 2018 Rishabh Joshi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.github.rishabh9.riko.upstox.common;

import net.jodah.failsafe.RetryPolicy;

import javax.annotation.Nonnull;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;

/**
* A simple factory to create policies for retrying when an API call fails.
* Riko uses the open source <a href="https://github.com/jhalterman/failsafe">Failsafe</a>
* library for implementing retries.
*
* @see RikoRetryPolicyFactory
*/
public interface RetryPolicyFactory {

/**
* @return A {@link RetryPolicy} that expresses when retries should be performed.
* An {@code empty} {@link RetryPolicy} indicates retries should be disabled.
*/
@Nonnull
Optional<RetryPolicy> createRetryPolicy();

/**
* @return A {@link ScheduledExecutorService} to allow for asynchronous executions.
* Cannot be {@code null}.
*/
@Nonnull
ScheduledExecutorService createExecutorService();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* MIT License
*
* Copyright (c) 2018 Rishabh Joshi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.github.rishabh9.riko.upstox.common;

import net.jodah.failsafe.RetryPolicy;

import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
* The Riko's default retry policy factory.
*
* @see RetryPolicyFactory
*/
public class RikoRetryPolicyFactory implements RetryPolicyFactory {

/**
* @return The default {@link RetryPolicy}
*/
@Override
public Optional<RetryPolicy> createRetryPolicy() {
return Optional.of(new RetryPolicy()
.retryOn(Throwable.class)
.withBackoff(1, 5, TimeUnit.SECONDS)
.withMaxRetries(3));
}

/**
* @return The default {@link ScheduledExecutorService} to be used by {@link RetryPolicy}.
*/
@Override
public ScheduledExecutorService createExecutorService() {
return Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
import com.github.rishabh9.riko.upstox.common.models.ApiCredentials;
import com.github.rishabh9.riko.upstox.common.models.AuthHeaders;
import com.github.rishabh9.riko.upstox.login.models.AccessToken;
import net.jodah.failsafe.RetryPolicy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nonnull;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;

/**
* Parent class for every Service class. Holds common methods.
Expand All @@ -41,13 +43,20 @@ public abstract class Service {
private static final Logger log = LogManager.getLogger(Service.class);

protected final UpstoxAuthService upstoxAuthService;
protected final RetryPolicy retryPolicy;
protected final ScheduledExecutorService retryExecutor;

/**
* @param upstoxAuthService The service to retrieve authentication details
*/
public Service(@Nonnull final UpstoxAuthService upstoxAuthService) {
public Service(@Nonnull final UpstoxAuthService upstoxAuthService,
@Nonnull final RetryPolicyFactory retryPolicyFactory) {

this.upstoxAuthService = Objects.requireNonNull(upstoxAuthService);
this.retryPolicy = Objects.requireNonNull(retryPolicyFactory).createRetryPolicy()
// The default behaviour is not to re-try.
.orElse(new RetryPolicy().withMaxRetries(0));
this.retryExecutor = Objects.requireNonNull(retryPolicyFactory).createExecutorService();
}

protected <T> T prepareServiceApi(@Nonnull final Class<T> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public void rebuildWithUrl(HttpUrl url) {
public <S> S createService(@Nonnull final Class<S> serviceClass) {

log.debug("Creating service without authentication");
return createService(Objects.requireNonNull(serviceClass), null, null);
return createService(Objects.requireNonNull(serviceClass), null);
}

/**
Expand All @@ -141,19 +141,14 @@ public <S> S createService(@Nonnull final Class<S> serviceClass) {
* @return The retrofitted service
*/
public <S> S createService(@Nonnull final Class<S> serviceClass,
@Nullable final String username,
@Nullable final String password) {
@Nonnull final String username,
@Nonnull final String password) {

if (!Strings.isNullOrEmpty(username)
&& !Strings.isNullOrEmpty(password)) {
final String authToken = Credentials.basic(username, password);
log.debug("Creating service with Basic authentication");
return createService(
Objects.requireNonNull(serviceClass),
new AuthHeaders(authToken, username));
}
// Setup request headers without any auth
return createService(Objects.requireNonNull(serviceClass), null);
new AuthHeaders(Objects.requireNonNull(authToken), Objects.requireNonNull(username)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.github.rishabh9.riko.upstox.common.constants;

public final class LiveFeedType {
public static final String LTP = "LTP";
public static final String FULL = "Full";
public static final String LTP = "ltp";
public static final String FULL = "full";
public static final String ALL = "all";
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ public class PropertyKeys {
public static final int RIKO_WS_SERVER_PORT_DEFAULT = 443;

public static final String RIKO_WS_RECONNECT = "riko.ws.reconnect";
public static final String RIKO_WS_RECONNECT_DEFAULT = "true";
public static final String RIKO_WS_RECONNECT_DEFAULT = "false";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* MIT License
*
* Copyright (c) 2018 Rishabh Joshi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package com.github.rishabh9.riko.upstox.common.constants;

public class RateLimits {
public static final double LIVE_FEED_RATE_LIMIT = 1.0D;
public static final double SUBSCRIBE_RATE_LIMIT = 1.0D;
public static final double UNSUBSCRIBE_RATE_LIMIT = 1.0D;
public static final double SYMBOLS_SUBSCRIBED_RATE_LIMIT = 1.0D;
public static final double HISTORICAL_RATE_LIMIT = 10.0D;
public static final double LOGIN_RATE_LIMIT = 1.0D;
public static final double ORDER_HISTORY_RATE_LIMIT = 1.0D;
public static final double ORDER_DETAILS_RATE_LIMIT = 1.0D;
public static final double TRADE_BOOK_RATE_LIMIT = 1.0D;
public static final double TRADE_HISTORY_RATE_LIMIT = 1.0D;
public static final double PLACE_ORDER_RATE_LIMIT = 10.0D;
public static final double MODIFY_ORDER_RATE_LIMIT = 1.0D;
public static final double CANCEL_ORDER_RATE_LIMIT = 1.0D;
public static final double PROFILE_RATE_LIMIT = 1.0D;
public static final double BALANCE_RATE_LIMIT = 1.0D;
public static final double POSITIONS_RATE_LIMIT = 1.0D;
public static final double HOLDINGS_RATE_LIMIT = 1.0D;
public static final double MASTER_CONTRACT_RATE_LIMIT = 1.0D;
public static final double WS_PARAMS_RATE_LIMIT = 1.0D;
public static final double WEB_SOCKET_RATE_LIMIT = 1.0D;
}
10 changes: 10 additions & 0 deletions src/main/java/com/github/rishabh9/riko/upstox/feed/FeedApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import com.github.rishabh9.riko.upstox.common.models.UpstoxResponse;
import com.github.rishabh9.riko.upstox.feed.models.Feed;
import com.github.rishabh9.riko.upstox.feed.models.Subscription;
import com.github.rishabh9.riko.upstox.feed.models.SubscriptionResponse;
import retrofit2.http.GET;
import retrofit2.http.Path;
Expand Down Expand Up @@ -76,4 +77,13 @@ CompletableFuture<UpstoxResponse<SubscriptionResponse>> subscribe(@Path("type")
CompletableFuture<UpstoxResponse<SubscriptionResponse>> unsubscribe(@Path("type") String type,
@Path("exchange") String exchange,
@Query("symbol") String symbolsCsv);

/**
* Get list of symbols subscribed.
*
* @param type 'all' or 'ltp' or 'full'.
* @return A CompletableFuture to execute the request (a)synchronously.
*/
@GET("/live/feed/{type}")
CompletableFuture<UpstoxResponse<Subscription>> symbolsSubscribed(@Path("type") String type);
}
Loading

0 comments on commit a8fe6a4

Please sign in to comment.