Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c979738
brokers added
Sep 11, 2024
0b460f7
sync.yml
sathishadhirav Sep 11, 2024
3a957ff
Update main.yml
sathishadhirav Sep 11, 2024
2c96f53
Update main.yml
sathishadhirav Sep 11, 2024
2d1c5e1
Update main.yml
sathishadhirav Sep 11, 2024
fc976a8
Update main.yml
sathishadhirav Sep 11, 2024
899af83
Update main.yml
sathishadhirav Sep 11, 2024
7d38038
Update main.yml
sathishadhirav Sep 11, 2024
1ac44f3
Update main.yml
sathishadhirav Sep 11, 2024
ab20721
Update main.yml
sathishadhirav Sep 11, 2024
f52a3e6
Update main.yml
sathishadhirav Sep 11, 2024
c61976f
Update main.yml
sathishadhirav Sep 11, 2024
3a5ad5a
Update main.yml
sathishadhirav Sep 11, 2024
ae98f11
Update main.yml
sathishadhirav Sep 11, 2024
689fe71
Update main.yml
sathishadhirav Sep 11, 2024
3ad9dc7
Update main.yml
sathishadhirav Sep 11, 2024
fa96043
Update main.yml
sathishadhirav Sep 11, 2024
c893141
Update main.yml
sathishadhirav Sep 11, 2024
2423ab8
Update main.yml
sathishadhirav Sep 11, 2024
1628297
Update main.yml
sathishadhirav Sep 11, 2024
c72fcea
Update main.yml
sathishadhirav Sep 11, 2024
7217134
Update main.yml
sathishadhirav Sep 12, 2024
cda0b14
Update main.yml
sathishadhirav Sep 12, 2024
eb30ac8
Update main.yml
sathishadhirav Sep 12, 2024
3730734
Update main.yml
sathishadhirav Sep 12, 2024
1b06313
Update main.yml
sathishadhirav Sep 12, 2024
606c19e
Update main.yml
sathishadhirav Sep 12, 2024
7cb6bb2
Update main.yml
sathishadhirav Sep 12, 2024
4787146
Update main.yml
sathishadhirav Sep 12, 2024
59197b2
Update main.yml
sathishadhirav Sep 12, 2024
3374ffa
Update main.yml
sathishadhirav Sep 12, 2024
71def3f
Update main.yml
sathishadhirav Sep 12, 2024
f15c342
Update main.yml
sathishadhirav Sep 12, 2024
a87ca58
Update main.yml
sathishadhirav Sep 12, 2024
f7f1ed0
Update main.yml
sathishadhirav Sep 12, 2024
8936525
Update main.yml
sathishadhirav Sep 12, 2024
0a3f34c
Update main.yml
sathishadhirav Sep 12, 2024
1e048e4
Update main.yml
sathishadhirav Sep 12, 2024
d184e13
Update main.yml
sathishadhirav Sep 12, 2024
63bccee
Update main.yml
sathishadhirav Sep 12, 2024
fd6021f
Update main.yml
sathishadhirav Sep 12, 2024
3750e38
Update main.yml
sathishadhirav Sep 12, 2024
632d10d
Update main.yml
sathishadhirav Sep 12, 2024
34f375e
Update main.yml
sathishadhirav Sep 12, 2024
560b99d
Update main.yml
sathishadhirav Sep 12, 2024
e062761
Update main.yml
sathishadhirav Sep 12, 2024
2d0ba07
Create merge.yml
sathishadhirav Sep 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Sync from GitLab and Create Pull Request

on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to sync from GitLab'
required: true
default: 'main'
schedule:
- cron: '0 12 * * *' # Runs every day at 12:00 UTC

jobs:
sync:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
# Step 1: Checkout GitHub repository
- name: Checkout GitHub repository
uses: actions/checkout@v3
with:
fetch-depth: 0 # Required to pull all history and branches
token: ${{ secrets.GITHUB_TOKEN }}

# Step 2: Set Git identity
- name: Set git identity
run: |-
git config user.name "github-actions"
git config user.email "[email protected]"

- id: find_mutations
name: Find mutations
run: |-
mkdir -p gitlab-repo
cd gitlab-repo
git init
git remote add origin https://${{ secrets.GITLAB_USERNAME }}:${{ secrets.GITLAB_TOKEN }}@git.mtapi.io/root/mt5-java-api.git
git fetch origin
git pull origin main
ls
rm -rf .git
rm -rf .github
rm -rf META-INF
rm -rf .gitlab-ci.yml
rm -rf README.md
rm -rf pg.txt
grep -rl 'mtapi.mt5' .
grep -rl 'mtapi.mt5' . | xargs sed -i 's/mtapi.mt5/io.quantum.trading.brokers.forex.mt5protocol.mtapi.mt5/g'
cd ..
git add gitlab-repo/**
git diff --staged --patch --exit-code > .repo.patch || echo "patch_created=true" >> $GITHUB_OUTPUT
git clean -df
# Step 4: Create Pull Request if changes are found
- name: Create Pull Request in GitHub
if: ${{ steps.find_mutations.outputs.patch_created == 'true' }}
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
add-paths: |
brokers/src/main/java/io/quantum/trading/brokers/forex/mt5protocol/**
commit-message: |-
feat: Adding/Updating gitlab-files
[Workflow Run]: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
branch: kumar
title: "feat: Add a new commited files from GitLab"
body: |-
This pull request is created automatically by GitHub Actions to sync changes from GitLab.

[Workflow Run]: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
author: github-actions <[email protected]>
committer: github-actions <[email protected]>
signoff: true
18 changes: 18 additions & 0 deletions .github/workflows/merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Build and Create Docker Image on Merge

on:
pull_request:
types: [closed]
branches:
- main

jobs:
build:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
55 changes: 55 additions & 0 deletions brokers/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quantum</groupId>
<artifactId>trading</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>

<artifactId>brokers</artifactId>

<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
<dependency>
<groupId>io.quantum</groupId>
<artifactId>core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<includes>
<include>*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>
13 changes: 13 additions & 0 deletions brokers/src/main/java/io/quantum/trading/BrokerApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quantum.trading;

import io.quantum.trading.util.DateUtil;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BrokerApplication {
public static void main(String[] args) {
DateUtil.setTimeZone();
SpringApplication.run(BrokerApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.quantum.trading.brokers;

public interface AllowBacktesting {
void synchronizeOrders();

boolean isInBacktestMode();

boolean isUtMode();
}
33 changes: 33 additions & 0 deletions brokers/src/main/java/io/quantum/trading/brokers/Broker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quantum.trading.brokers;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class Broker {
protected static final String TAG_PREFIX = "QUANTUM_BOT";
protected static final String DUMMY_TRADE = "NO_TRADE";

public abstract double getBalance() throws BrokerException;

public abstract Currency getCurrency() throws BrokerException;

public abstract boolean testConnection() throws BrokerException;

public abstract void disConnect() throws BrokerException;

public abstract BrokerOrderDetail placeOrder(BrokerPlaceOrderRequest brokerPlaceOrderRequest)
throws BrokerException;

public abstract BrokerOrderDetail modifyOrder(BrokerModifyOrderRequest brokerModifyOrderRequest)
throws BrokerException;

public abstract void cancelOrder(String orderId) throws BrokerException;

public abstract void closeOrder(String orderId) throws BrokerException;

public abstract BrokerOrderDetail getOrderDetails(String orderId) throws BrokerException;

public boolean isDemoAcc() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quantum.trading.brokers;

import io.quantum.trading.exception.ApiError;
import io.quantum.trading.exception.EntityException;
import lombok.Getter;

public class BrokerException extends EntityException {
@Getter private boolean retryable = true;

public BrokerException(Throwable cause, ApiError apiError, Object... params) {
super(cause, apiError, params);
}

public BrokerException(ApiError apiError, Object... params) {
super(apiError, params);
}

public BrokerException(boolean retryable, Throwable cause, ApiError apiError, Object... params) {
super(cause, apiError, params);
this.retryable = retryable;
}

public BrokerException(boolean retryable, BrokerException exception) {
super(exception);
this.retryable = retryable;
}
}
125 changes: 125 additions & 0 deletions brokers/src/main/java/io/quantum/trading/brokers/BrokerFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package io.quantum.trading.brokers;

import io.quantum.trading.brokers.forex.mt5.MT5Broker;
import io.quantum.trading.brokers.forex.mt5.Mt5BacktestBroker;
import io.quantum.trading.brokers.indian.GlobalDataFeed;
import io.quantum.trading.brokers.indian.IndianDemoBroker;
import io.quantum.trading.brokers.indian.NseBroker;
import io.quantum.trading.brokers.indian.ZerodhaBroker;
import io.quantum.trading.brokers.indian.fyers.FyersBroker;
import io.quantum.trading.entities.*;
import io.quantum.trading.entities.BrokerConfigDetails.Mt5BrokerConfigDetails;
import io.quantum.trading.redis.RedisCrudService;
import io.quantum.trading.services.ScriptMetadataRefresherService;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BrokerFactory {
private final BrokerConfigRepository brokerConfigRepository;
private final DemoBrokerRepository demoBrokerRepository;
private final RedisCrudService redisCrudService;
private final ScriptMetadataRefresherService scriptMetadataRefresherService;
private static final Map<String, Broker> BROKERS = new ConcurrentHashMap<>();

public Broker getBroker(String brokerConfigId) {
synchronized (brokerConfigId.intern()) {
if (!BROKERS.containsKey(brokerConfigId)) {
log.info("Broker, {} is not cached. Creating a new one", brokerConfigId);
var brokerConfigOpt = brokerConfigRepository.findById(brokerConfigId);
if (brokerConfigOpt.isEmpty())
throw new RuntimeException("BrokerConfigId, " + brokerConfigId + " is not found");

var brokerConfig = brokerConfigOpt.get();

var broker =
switch (brokerConfig.getType()) {
case BrokerConfig.BrokerType.ZERODHA ->
new ZerodhaBroker(() -> brokerConfigRepository.findById(brokerConfigId).get());
case BrokerConfig.BrokerType.MT5 ->
new MT5Broker((Mt5BrokerConfigDetails) brokerConfig.getBrokerConfigDetails());
case BrokerConfig.BrokerType.MT5_BACKTEST ->
new Mt5BacktestBroker(
(BrokerConfigDetails.Mt5BacktestBrokerConfigDetails)
brokerConfig.getBrokerConfigDetails(),
redisCrudService);
case BrokerConfig.BrokerType.GLOBAL_DATAFEEDS ->
new GlobalDataFeed(
(BrokerConfigDetails.GlobalDataFeedConfigDetails)
brokerConfig.getBrokerConfigDetails());
case BrokerConfig.BrokerType.INDIAN_MKT_DEMO,
BrokerConfig.BrokerType.INDIAN_MKT_BACKTEST ->
new IndianDemoBroker(brokerConfig, redisCrudService, demoBrokerRepository);
case BrokerConfig.BrokerType.FYERS ->
new FyersBroker(
(BrokerConfigDetails.FyersBrokerConfigDetails)
brokerConfig.getBrokerConfigDetails());

default ->
throw new IllegalArgumentException(
"Unknown broker type, " + brokerConfig.getType());
};
BROKERS.put(brokerConfigId, broker);
synchronized (BrokerFactory.class) {
getScriptMetadataMap(BatchLastRunDetails.BatchType.NSE_SCRIPT_METADATA);
getScriptMetadataMap(BatchLastRunDetails.BatchType.FOREX_SCRIPT_METADATA);
}
}
}
return BROKERS.get(brokerConfigId);
}

private synchronized void getScriptMetadataMap(BatchLastRunDetails.BatchType batchType) {
var scriptMetadataRes =
scriptMetadataRefresherService.metadataWatcher(
batchType,
"BrokerFactoryCb",
scriptMetadata -> {
updateMetadataInBrokers(scriptMetadata);
return null;
});
updateMetadataInBrokers(scriptMetadataRes);
}

private void updateMetadataInBrokers(List<? extends ScriptMetadata> scriptMetadata) {
if (!scriptMetadata.isEmpty()) {
if (scriptMetadata.get(0) instanceof NseScriptMetadata) {
log.info("Updating NSE brokers with latest metadata");
var nseScriptMetadataMap =
((List<NseScriptMetadata>) scriptMetadata)
.stream()
.collect(
Collectors.toMap(
NseScriptMetadata::getId, nseScriptMetadata -> nseScriptMetadata));
// TODO The moment we introduce the 2nd NseBroker, we have to make the below code dynamic
var scriptTokenSymbolMap =
nseScriptMetadataMap.entrySet().stream()
.collect(
Collectors.groupingBy(
e ->
Long.parseLong(
e.getValue()
.getBrokerScriptIdMap()
.get(BrokerConfig.BrokerType.ZERODHA)),
Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
BROKERS.values().stream()
.filter(broker -> broker instanceof NseBroker)
.forEach(
broker -> {
((NseBroker) broker)
.updateScriptMetadata(nseScriptMetadataMap, scriptTokenSymbolMap);
});
} else if (scriptMetadata.get(0) instanceof ForexScriptMetadata) {
// Do nothing
}
}
}
}
Loading