diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 08658d07b..a2742fa53 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,18 +4,28 @@ updates: directory: "/" schedule: interval: "weekly" - day: "friday" + day: "thursday" time: "18:00" timezone: Europe/Paris - open-pull-requests-limit: 10 + open-pull-requests-limit: 9 target-branch: development - - package-ecosystem: "npm" + - package-ecosystem: maven + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + time: "18:00" + timezone: Europe/Paris + open-pull-requests-limit: 9 + target-branch: development + + - package-ecosystem: npm directory: "/docs" schedule: interval: "weekly" - day: "friday" + day: "sunday" time: "18:00" timezone: Europe/Paris - open-pull-requests-limit: 10 + open-pull-requests-limit: 9 target-branch: development \ No newline at end of file diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/branch-push-or-pull-request.yml similarity index 70% rename from .github/workflows/continuous-integration.yml rename to .github/workflows/branch-push-or-pull-request.yml index 50bc1154f..17d3c696d 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/branch-push-or-pull-request.yml @@ -1,71 +1,44 @@ -name: Continuous integration +name: Branch push or pull request -on: - push: - branches: - - "development" +on: [push, pull_request] jobs: build: - # ================================================================================================================== - # Configuration. runs-on: ubuntu-latest steps: - # ================================================================================================================ - - name: GPG Setup - env: - GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} - run: | - echo "$GPG_PRIVATE_KEY" > private.asc - gpg --import --batch private.asc - # ================================================================================================================ - name: JDK 11 Setup uses: actions/setup-java@v2 with: distribution: 'adopt' java-version: '11' - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD # ================================================================================================================ - name: Retrieve the sources uses: actions/checkout@v2 # ================================================================================================================ - - name: Build, run tests, package and deploy to Maven central - env: # Environment variables. - # GPG. - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - # OSSRH credentials. - MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + - name: Build, run tests and deploy locally + id: maven run: | - mvn deploy -B -Dgpg.passphrase=${GPG_PASSPHRASE} + mvn install -Dgpg.skip + echo "::set-output name=version::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" # ================================================================================================================ - name: Upload codacy coverage results - continue-on-error: true run: | bash <(curl -Ls https://coverage.codacy.com/get.sh) report \ --project-token ${{ secrets.CODACY_API_TOKEN }} \ -r spring-boot-starter/autoconfigure/target/site/jacoco/jacoco.xml - # ================================================================================================================ - - name: Retrieve the version from Maven pom - id: version - run: | - echo "::set-output name=version::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" - # ================================================================================================================ - name: Test Cassandre trading bot maven archetype - basic strategy run: | mvn -B archetype:generate \ -DarchetypeGroupId=tech.cassandre.trading.bot \ -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ - -DarchetypeVersion=${{ steps.version.outputs.version }} \ + -DarchetypeVersion=${{ steps.maven.outputs.version }} \ -DgroupId=com.example \ -DartifactId=archetype-test-basic \ -Dversion=1.0-SNAPSHOT \ @@ -78,7 +51,7 @@ jobs: mvn -B archetype:generate \ -DarchetypeGroupId=tech.cassandre.trading.bot \ -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-ta4j-archetype \ - -DarchetypeVersion=${{ steps.version.outputs.version }} \ + -DarchetypeVersion=${{ steps.maven.outputs.version }} \ -DgroupId=com.example \ -DartifactId=archetype-test-ta4j-basic \ -Dversion=1.0-SNAPSHOT \ @@ -89,22 +62,22 @@ jobs: # Testing that the graphql starter is working correctly. - name: Start a postgres server and restore a database from production run: | + docker pull library/postgres:13-alpine docker run -d \ --name postgres \ -p 5432:5432 \ -e POSTGRES_DB=cassandre_trading_bot \ -e POSTGRES_USER=cassandre_trading_bot \ -e POSTGRES_PASSWORD=cassandre_trading_bot_password \ + -v $(pwd)/util/test/api/graphql/dump_cassandre_trading_bot.sql:/docker-entrypoint-initdb.d/dump_cassandre_trading_bot.sql \ library/postgres:13-alpine - sleep 30 - docker exec -i postgres psql -U cassandre_trading_bot cassandre_trading_bot < util/test/api/graphql/dump_cassandre_trading_bot.sql - name: Creating a trading bot and configure it for the postgres database run: | mvn -B archetype:generate \ -DarchetypeGroupId=tech.cassandre.trading.bot \ -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ - -DarchetypeVersion=${{ steps.version.outputs.version }} \ + -DarchetypeVersion=${{ steps.maven.outputs.version }} \ -DgroupId=com.example \ -DartifactId=archetype-test-api-graphql \ -Dversion=1.0-SNAPSHOT \ @@ -114,11 +87,10 @@ jobs: cp util/test/api/graphql/application.properties archetype-test-api-graphql/src/main/resources/ cp util/test/api/graphql/user-trade.tsv archetype-test-api-graphql/src/main/resources/ mvn -f archetype-test-api-graphql/pom.xml spring-boot:run & + sleep 60 - name: Runs graphQL tests. run: | - sleep 30 - cp util/test/api/graphql/package.json . - cp util/test/api/graphql/*.js . + cd util/test/api/graphql npm install --save-dev jest isomorphic-fetch - npm run test + npm run test \ No newline at end of file diff --git a/.github/workflows/branch-push.yml b/.github/workflows/branch-push.yml deleted file mode 100644 index 26330f9ed..000000000 --- a/.github/workflows/branch-push.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Branch push - -on: - push: - branches-ignore: - - development - - master - pull_request: - -jobs: - build: - # ================================================================================================================== - # Configuration. - runs-on: ubuntu-latest - - steps: - # ================================================================================================================ - - name: JDK 11 Setup - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: '11' - - # ================================================================================================================ - - name: Retrieve the sources - uses: actions/checkout@v2 - - # ================================================================================================================ - - name: Build, run tests, package and deploy to Maven central - run: | - mvn install -Dgpg.skip - - # ================================================================================================================ - - name: Retrieve the version from Maven pom - id: version - run: | - echo "::set-output name=version::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" - - # ================================================================================================================ - - name: Test Cassandre trading bot maven archetype - basic strategy - run: | - mvn -B archetype:generate \ - -DarchetypeGroupId=tech.cassandre.trading.bot \ - -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ - -DarchetypeVersion=${{ steps.version.outputs.version }} \ - -DgroupId=com.example \ - -DartifactId=archetype-test-basic \ - -Dversion=1.0-SNAPSHOT \ - -Dpackage=com.example - mvn -f archetype-test-basic/pom.xml test - - # ================================================================================================================ - - name: Test Cassandre trading bot maven archetype - basic ta4j strategy - run: | - mvn -B archetype:generate \ - -DarchetypeGroupId=tech.cassandre.trading.bot \ - -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-ta4j-archetype \ - -DarchetypeVersion=${{ steps.version.outputs.version }} \ - -DgroupId=com.example \ - -DartifactId=archetype-test-ta4j-basic \ - -Dversion=1.0-SNAPSHOT \ - -Dpackage=com.example - mvn -f archetype-test-ta4j-basic/pom.xml test diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4266d74f8..f5568113a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,14 +1,12 @@ -name: "CodeQL" +name: CodeQL analysis on: schedule: - - cron: '0 17 * * FRI' + - cron: '0 18 * * THU' + - cron: '0 18 * * SUN' jobs: analyze: - # ================================================================================================================== - # Configuration. - name: Analyze runs-on: ubuntu-latest steps: @@ -24,17 +22,16 @@ jobs: uses: actions/checkout@v2 # ================================================================================================================ - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1.0.7 + uses: github/codeql-action/init@v1.0.22 with: languages: java # ================================================================================================================ - - name: Build, run tests and package + - name: Build and package run: | - mvn package + mvn package -DskipTests # ================================================================================================================ - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1.0.7 + uses: github/codeql-action/analyze@v1.0.22 diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index d661a1a0e..a2cd5dcc7 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -2,12 +2,11 @@ name: Integration tests on: schedule: - - cron: '0 17 * * FRI' + - cron: '0 18 * * THU' + - cron: '0 18 * * SUN' jobs: build: - # ================================================================================================================== - # Configuration. runs-on: ubuntu-latest steps: @@ -23,8 +22,8 @@ jobs: uses: actions/checkout@v2 # ================================================================================================================ - - name: Build, run tests, package and deploy to Maven central - Also sends Qase tests reports - env: # Environment variables. + - name: Build and run integration tests + env: # Kucoin credentials. KUCOIN_NAME: ${{ secrets.KUCOIN_NAME }} KUCOIN_USERNAME: ${{ secrets.KUCOIN_USERNAME }} @@ -50,4 +49,4 @@ jobs: BINANCE_KEY: ${{ secrets.BINANCE_KEY }} BINANCE_SECRET: ${{ secrets.BINANCE_SECRET }} run: | - mvn -Pintegration package + mvn test -Pintegration diff --git a/.github/workflows/publish-snapshot-and-website.yml b/.github/workflows/publish-snapshot-and-website.yml new file mode 100644 index 000000000..99960ecd8 --- /dev/null +++ b/.github/workflows/publish-snapshot-and-website.yml @@ -0,0 +1,82 @@ +name: Publish snapshot and website + +on: + push: + branches: + - "development" + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # ================================================================================================================ + - name: JDK 11 Setup + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + # ================================================================================================================ + - name: Retrieve the sources + uses: actions/checkout@v2 + + # ================================================================================================================ + - name: GPG Setup + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + run: | + echo "$GPG_PRIVATE_KEY" > private.asc + gpg --import --batch private.asc + + # ================================================================================================================ + - name: Build, package and deploy to Maven central + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Ossrh credentials. + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} + # GPG. + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: | + mvn deploy -B -DskipTests=true -Dgpg.passphrase=${GPG_PASSPHRASE} + + # ================================================================================================================ + - name: Retrieve the latest release published on Github + uses: pozetroninc/github-action-get-latest-release@v0.5.0 + id: getLatestRelease + with: + repository: ${{ github.repository }} + + # ================================================================================================================ + - name: Install Go to generate the graphQL documentation with gqldoc + uses: actions/setup-go@v2 + with: + go-version: '^1.17.3' + + # ================================================================================================================ + - name: Add the GraphQL schema and its documentation to the website + run: | + cp spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/src/main/resources/schema/*.graphqls docs/docs/.vuepress/public/api/graphql/definition + go install github.com/Code-Hex/gqldoc/cmd/gqldoc@v0.0.4 + gqldoc -s "docs/docs/.vuepress/public/api/graphql/definition/*.graphqls" -o ./docs/docs/learn/graphql-api-documentation + + # ================================================================================================================ + - name: Install vuepress, set release number, and build the website + run: | + yarn add -D vuepress@next + find . -type f -name "*.md" -exec sed -i 's/CASSANDRE_LATEST_RELEASE/${{ steps.getLatestRelease.outputs.release }}/g' {} \; + yarn --cwd docs install + yarn --cwd docs docs:build docs + + # ================================================================================================================ + - name: Deploy the website to github pages + uses: JamesIves/github-pages-deploy-action@4.1.4 + with: + branch: gh-pages + folder: docs/docs/.vuepress/dist + commit-message: "Website update" + clean: true diff --git a/.github/workflows/release-creation.yml b/.github/workflows/release-creation.yml index f5274b9d3..a7d1be699 100644 --- a/.github/workflows/release-creation.yml +++ b/.github/workflows/release-creation.yml @@ -7,19 +7,9 @@ on: jobs: build: - # ================================================================================================================== - # Configuration. runs-on: ubuntu-latest steps: - # ================================================================================================================ - - name: GPG Setup - env: - GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} - run: | - echo "$GPG_PRIVATE_KEY" > private.asc - gpg --import --batch private.asc - # ================================================================================================================ - name: JDK 11 Setup uses: actions/setup-java@v2 @@ -35,9 +25,17 @@ jobs: uses: actions/checkout@v2 # ================================================================================================================ - - name: Build, package and deploy - id: package - env: # Environment variables. + - name: GPG Setup + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + run: | + echo "$GPG_PRIVATE_KEY" > private.asc + gpg --import --batch private.asc + + # ================================================================================================================ + - name: Build, package and deploy to Maven central + id: maven + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Ossrh credentials. MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} @@ -49,67 +47,16 @@ jobs: echo "::set-output name=version::$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" # ================================================================================================================ - - name: Create the release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Create the release in GitHub + uses: marvinpinto/action-automatic-releases@v1.2.1 with: - tag_name: ${{ steps.package.outputs.version }} - release_name: ${{ steps.package.outputs.version }} - body: ${{ steps.package.outputs.version }} + repo_token: ${{ secrets.GITHUB_TOKEN }} + title: ${{ steps.maven.outputs.version }} draft: false prerelease: false # ================================================================================================================ - # Upload cassandre-trading-bot-spring-boot-autoconfigure assets to the release (jar, sources, javadoc). - - name: Upload cassandre-trading-bot-spring-boot-autoconfigure jar - continue-on-error: true - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: spring-boot-starter/autoconfigure/target/cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}.jar - asset_name: cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}.jar - asset_content_type: application/java-archive - - - name: Upload cassandre-trading-bot-spring-boot-autoconfigure sources - continue-on-error: true - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: spring-boot-starter/autoconfigure/target/cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}-sources.jar - asset_name: cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}-sources.jar - asset_content_type: application/java-archive - - - name: Upload cassandre-trading-bot-spring-boot-autoconfigure javadoc - continue-on-error: true - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: spring-boot-starter/autoconfigure/target/cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}-javadoc.jar - asset_name: cassandre-trading-bot-spring-boot-autoconfigure-${{ steps.package.outputs.version }}-javadoc.jar - asset_content_type: application/java-archive - - # ================================================================================================================ - # Upload cassandre-trading-bot-spring-boot-starter assets to the release (jar). - - name: Upload cassandre-trading-bot-spring-boot-starter jar - continue-on-error: true - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: spring-boot-starter/starter/target/cassandre-trading-bot-spring-boot-starter-${{ steps.package.outputs.version }}.jar - asset_name: cassandre-trading-bot-spring-boot-starter-${{ steps.package.outputs.version }}.jar - asset_content_type: application/java-archive - - # ================================================================================================================ - - name: Publish the release announce on Twitter + - name: Publish the announce on Twitter continue-on-error: true uses: ethomson/send-tweet-action@v1 env: @@ -118,45 +65,17 @@ jobs: TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} with: - status: "Cassandre trading bot ${{ steps.package.outputs.version }} released - More information here : ${{ steps.create_release.outputs.html_url }}" + status: "Cassandre trading bot ${{ steps.maven.outputs.version }} released - More information here: https://github.com/cassandre-tech/cassandre-trading-bot/releases/tag/${{ steps.maven.outputs.version }}" consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }} consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} # ================================================================================================================ - - name: Publish the release announce on Discord + - name: Publish the announce on Discord continue-on-error: true uses: Ilshidur/action-discord@0.3.0 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: - args: "Cassandre trading bot ${{ steps.package.outputs.version }} released - More information here : ${{ steps.create_release.outputs.html_url }}" - - # ================================================================================================================ - - uses: pozetroninc/github-action-get-latest-release@master - id: getLatestRelease - with: - repository: ${{ github.repository }} - - # ================================================================================================================ - - name: Change release in website sources - run: find . -type f -name "*.md" -exec sed -i 's/CASSANDRE_LATEST_RELEASE/${{ steps.getLatestRelease.outputs.release }}/g' {} \; - - # ================================================================================================================ - - name: Install vuepress and build the documentation website - run: | - yarn add -D vuepress - cd docs - yarn install - cd .. - yarn --cwd docs build docs - - # ================================================================================================================ - - name: Deploy the documentation website - uses: JamesIves/github-pages-deploy-action@4.1.4 - with: - branch: gh-pages - folder: docs/src/.vuepress/dist - commit-message: "Documentation website update" - clean: true + args: "Cassandre trading bot ${{ steps.maven.outputs.version }} released - More information here: https://github.com/cassandre-tech/cassandre-trading-bot/releases/tag/${{ steps.maven.outputs.version }}" diff --git a/.github/workflows/website-update.yml b/.github/workflows/website-update.yml deleted file mode 100644 index 7ac72b477..000000000 --- a/.github/workflows/website-update.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Website update - -on: - push: - branches: - - "development" - -jobs: - build: - # ================================================================================================================== - # Configuration. - runs-on: ubuntu-latest - - steps: - # ================================================================================================================ - - name: Retrieve the sources - uses: actions/checkout@v2 - - # ================================================================================================================ - - uses: pozetroninc/github-action-get-latest-release@master - id: getLatestRelease - with: - repository: ${{ github.repository }} - - # ================================================================================================================ - - name: Change release in website sources - run: find . -type f -name "*.md" -exec sed -i 's/CASSANDRE_LATEST_RELEASE/${{ steps.getLatestRelease.outputs.release }}/g' {} \; - - # ================================================================================================================ - - name: Install vuepress and build the documentation website - run: | - yarn add -D vuepress - cd docs - yarn install - cd .. - yarn --cwd docs build docs - - # ================================================================================================================ - - name: Deploy the documentation website - uses: JamesIves/github-pages-deploy-action@4.1.4 - with: - branch: gh-pages - folder: docs/src/.vuepress/dist - commit-message: "Documentation website update" - clean: true diff --git a/README.md b/README.md index 3a54acb69..9ea65e189 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +

+ Quick Start | + Documentation | + Discord | + Twitter +

+

Create and run your java crypto trading bot in minutes

+

Our Spring boot starter takes care of exchange connections, accounts, orders, trades, and positions so you can focus on building your strategies.

@@ -18,22 +26,27 @@ Cassandre trading bot on codacy + + Cassandre trading bot continuous integration + Cassandre trading bot on Maven Central repository

-

- Web site | - Quick Start | - Twitter | - Contact us -

-
+## ✨ Features +- **Get into trading with minimum fuss**: Available as a Spring boot starter, Cassandre takes care of exchange connection, accounts, orders, trades, and positions, so you can focus on building your strategy. +- **Create your strategy in minutes**: Just code when you want to create short/long positions, set the rules, and we take care of everything (buying, selling, rules management, orders, trades, and tickers). +- **Several exchanges supported**: Cassandre uses XChange library to connect to multiple exchanges. We test each Cassandre releases with Kucoin, Coinbase & Binance to be sure it works for you. +- **Dry mode**: We provide a dry mode to simulate a virtual exchange replying to your orders, so you can easily test your strategy. This way, you can simulate your gains/loss over a period of time. +- **Backtesting**: We provide a spring boot starter to backtest your bot on historical data. With this, during tests, Cassandre will import your data and push them to your strategy. +- **Technical Analysis support**: Cassandre provides a specific class (BasicTa4jCassandreStrategy) to help you build a strategy based on the open source technical analysis library ta4j. +

- - Cassandre trading bot continuous integration - + Quick Start | + Documentation | + Discord | + Twitter

\ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore old mode 100755 new mode 100644 index 595e21518..0090a25a6 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,12 +1,5 @@ -pids -logs node_modules -npm-debug.log -coverage/ -run -dist -.DS_Store -.nyc_output -.basement -config.local.js -basement_dist +.temp +.cache +.dist +package-lock.json \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..771b78992 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ +# Web site management. +[https://trading-bot.cassandre.tech/](https://trading-bot.cassandre.tech/) + +## Run the website +``` +cd docs +yarn docs:dev +``` \ No newline at end of file diff --git a/docs/src/.vuepress/config.js b/docs/docs/.vuepress/config.ts old mode 100755 new mode 100644 similarity index 58% rename from docs/src/.vuepress/config.js rename to docs/docs/.vuepress/config.ts index fc9c1a8ea..7490aec88 --- a/docs/src/.vuepress/config.js +++ b/docs/docs/.vuepress/config.ts @@ -1,21 +1,12 @@ -const {description} = require('../../package') +import {defineUserConfig} from 'vuepress' +import type {DefaultThemeOptions} from 'vuepress' -module.exports = { - /** - * Ref:https://v1.vuepress.vuejs.org/config/#title - */ - title: 'Cassandre', +export default defineUserConfig({ + lang: 'en-US', + title: 'Cassandre trading bot', + description: 'Create your Java crypto trading bot in minutes', - /** - * Ref:https://v1.vuepress.vuejs.org/config/#description - */ - description: 'Cassandre makes it easy to create your Java crypto trading bot. Our Spring boot starter takes care of exchange connections, accounts, orders, trades, and positions', - - /** - * Extra tags to be injected to the page HTML `` - * - * ref:https://v1.vuepress.vuejs.org/config/#head - */ + // Head head: [ ['meta', {name: 'theme-color', content: '#3eaf7c'}], ['meta', {name: 'apple-mobile-web-app-capable', content: 'yes'}], @@ -55,118 +46,145 @@ module.exports = { ['meta', {name: 'twitter:image:alt', content: 'Cassandre'}] ], - /** - * Theme configuration, here is the default theme configuration for VuePress. - * - * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html - */ themeConfig: { - repo: '', - editLinks: false, - docsDir: '', - editLinkText: '', lastUpdated: false, - nav: [ + contributors: false, + logo: 'assets/images/logo/cassandre-trading-bot-without-text.png', + logoDark: 'assets/images/logo/cassandre-trading-bot-without-text-dark-mode.png', + navbar: [ + // ========================================================================================================= + // Why Cassandre ? { text: 'Why Cassandre ?', - ariaLabel: 'Why Cassandre', - items: [ + children: [ {text: 'Overview', link: '/why-cassandre/overview'}, {text: 'Features & roadmap', link: '/why-cassandre/features-and-roadmap'}, - {text: 'Supported exchanges', link: '/why-cassandre/supported-cryptocurrency-exchanges'} + {text: 'Supported exchanges', link: '/why-cassandre/supported-cryptocurrency-exchanges'}, ] }, + // ========================================================================================================= + // Learn { text: 'Learn', - ariaLabel: 'Learn', - items: [ + children: [ + // ================================================================================================= { - text: 'Basics', items: [ + text: 'Basics', + children: [ {text: 'Quickstart', link: '/learn/quickstart'}, + {text: 'Exchange configuration', link: '/learn/exchange-connection-configuration'}, {text: 'Position management', link: '/learn/position-management'}, - {text: 'Dry mode & backtesting', link: '/learn/dry-mode-and-backtesting'}, + {text: 'Dry mode & backtesting', link: '/learn/dry-mode-and-backtesting'} ] }, + // ================================================================================================= { - text: 'Advanced', items: [ + text: 'Advanced', + children: [ {text: 'Technical analysis', link: '/learn/technical-analysis'}, {text: 'Data importation', link: '/learn/import-historical-data'}, - {text: 'GraphQL API', link: '/learn/graphql-api'}, + {text: 'GraphQL API', link: '/learn/graphql-api'} ] }, + // ================================================================================================= { - text: 'Structure', items: [ + text: 'Structure', + children: [ {text: 'Database', link: '/learn/database-structure'}, {text: 'Architecture', link: '/learn/architecture'}, ] } ] }, + // ========================================================================================================= + // Deploy & run { text: 'Deploy & run', - ariaLabel: 'Deploy & run', - items: [ - {text: 'Using Docker', link: '/deploy-and-run/docker'} + children: [ + {text: 'Using Docker', link: '/deploy-and-run/docker'}, ] }, + // ========================================================================================================= + // Ressources { text: 'Ressources', - ariaLabel: 'Ressources', - items: [ + children: [ + // ================================================================================================= { text: 'Trading', - ariaLabel: 'Trading', - items: [ - {text: 'Trading basics', link: '/ressources/trading-basics'}, + children: [ + {text: 'Trading basics', link: '/ressources/trading-basics'} ] }, + // ================================================================================================= { text: 'Things to read', - ariaLabel: 'Things to read', - items: [ - + children: [ {text: 'Articles', link: '/ressources/articles'}, - {text: 'Books', link: '/ressources/books'}, + {text: 'Books', link: '/ressources/books'} ] }, + // ================================================================================================= { - text: 'How-tos', items: [ - {text: 'Install development tools', link: '/ressources/how-tos/how-to-install-development-tools'}, + text: 'How-tos', + children: [ + { + text: 'Fix common problems', + link: '/ressources/how-tos/how-to-fix-common-problems.md' + }, + { + text: 'Install development tools', + link: '/ressources/how-tos/how-to-install-development-tools' + }, {text: 'Build from sources', link: '/ressources/how-tos/how-to-build-from-sources'}, {text: 'Create a release', link: '/ressources/how-tos/how-to-create-a-release'}, - {text: 'Create a Kucoin account', link: '/ressources/how-tos/how-to-create-a-kucoin-account'}, + { + text: 'Create a Kucoin account', + link: '/ressources/how-tos/how-to-create-a-kucoin-account' + } ] - }, - ], + } + ] }, + // ========================================================================================================= + // Contact { - text: 'Contact / Support', - ariaLabel: 'Contact', - items: [ + text: 'Contact / News', + children: [ {text: 'Email', link: 'mailto:contact@cassandre.tech'}, {text: 'Twitter', link: 'https://twitter.com/CassandreTech'}, {text: 'Discord', link: 'https://discord.gg/sv3VXuTgFS'}, - {text: 'Newsletter', link: 'https://cassandre.substack.com/'}, - ], + {text: 'Newsletter', link: 'https://cassandre.substack.com/'} + ] }, + // ========================================================================================================= + // Support us { text: 'Support us', link: 'https://opencollective.com/cassandre-tech' }, + // ========================================================================================================= + // Github { text: 'Github', link: 'https://github.com/cassandre-tech/cassandre-trading-bot' } ], - sidebar: 'auto' }, - /** - * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/ - */ + // Plugins plugins: [ - ['@vuepress/plugin-back-to-top'], - ['@vuepress/plugin-medium-zoom'], - ['@vuepress/plugin-google-analytics', {'ga': 'UA-158255496-1'}] + // Google analytics + ['@vuepress/plugin-google-analytics', {'id': 'UA-158255496-1'}], + // Docsearch + [ + '@vuepress/plugin-docsearch', + { + appId: 'BH4D9OD16A', + apiKey: '94f09cface8844077df616a30863e73a', + indexName: 'cassandre' + }, + ], ] -} + +}) \ No newline at end of file diff --git a/docs/docs/.vuepress/public/api/graphql/definition/.keep b/docs/docs/.vuepress/public/api/graphql/definition/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/src/.vuepress/public/assets/backup/Banner A.jpg b/docs/docs/.vuepress/public/assets/backup/Banner A.jpg similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Banner A.jpg rename to docs/docs/.vuepress/public/assets/backup/Banner A.jpg diff --git a/docs/src/.vuepress/public/assets/backup/Banner A.png b/docs/docs/.vuepress/public/assets/backup/Banner A.png similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Banner A.png rename to docs/docs/.vuepress/public/assets/backup/Banner A.png diff --git a/docs/src/.vuepress/public/assets/backup/Banner B.jpg b/docs/docs/.vuepress/public/assets/backup/Banner B.jpg similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Banner B.jpg rename to docs/docs/.vuepress/public/assets/backup/Banner B.jpg diff --git a/docs/src/.vuepress/public/assets/backup/Banner B.png b/docs/docs/.vuepress/public/assets/backup/Banner B.png similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Banner B.png rename to docs/docs/.vuepress/public/assets/backup/Banner B.png diff --git a/docs/src/.vuepress/public/assets/backup/Cassandre-B.jpg b/docs/docs/.vuepress/public/assets/backup/Cassandre-B.jpg similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Cassandre-B.jpg rename to docs/docs/.vuepress/public/assets/backup/Cassandre-B.jpg diff --git a/docs/src/.vuepress/public/assets/backup/Cassandre-B.png b/docs/docs/.vuepress/public/assets/backup/Cassandre-B.png similarity index 100% rename from docs/src/.vuepress/public/assets/backup/Cassandre-B.png rename to docs/docs/.vuepress/public/assets/backup/Cassandre-B.png diff --git a/docs/src/.vuepress/public/assets/backup/final.ai b/docs/docs/.vuepress/public/assets/backup/final.ai similarity index 100% rename from docs/src/.vuepress/public/assets/backup/final.ai rename to docs/docs/.vuepress/public/assets/backup/final.ai diff --git a/docs/src/.vuepress/public/assets/backup/final.eps b/docs/docs/.vuepress/public/assets/backup/final.eps similarity index 100% rename from docs/src/.vuepress/public/assets/backup/final.eps rename to docs/docs/.vuepress/public/assets/backup/final.eps diff --git a/docs/src/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-a.png b/docs/docs/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-a.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-a.png rename to docs/docs/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-a.png diff --git a/docs/src/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-b.png b/docs/docs/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-b.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-b.png rename to docs/docs/.vuepress/public/assets/images/banner/cassandre-trading-bot-banner-b.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/android-icon-192x192.png b/docs/docs/.vuepress/public/assets/images/favicon/android-icon-192x192.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/android-icon-192x192.png rename to docs/docs/.vuepress/public/assets/images/favicon/android-icon-192x192.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-114x114.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-114x114.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-114x114.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-114x114.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-120x120.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-120x120.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-120x120.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-120x120.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-144x144.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-144x144.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-144x144.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-144x144.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-152x152.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-152x152.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-152x152.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-152x152.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-180x180.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-180x180.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-180x180.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-180x180.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-57x57.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-57x57.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-57x57.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-57x57.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-60x60.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-60x60.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-60x60.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-60x60.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-72x72.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-72x72.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-72x72.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-72x72.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/apple-icon-76x76.png b/docs/docs/.vuepress/public/assets/images/favicon/apple-icon-76x76.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/apple-icon-76x76.png rename to docs/docs/.vuepress/public/assets/images/favicon/apple-icon-76x76.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/browserconfig.xml b/docs/docs/.vuepress/public/assets/images/favicon/browserconfig.xml similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/browserconfig.xml rename to docs/docs/.vuepress/public/assets/images/favicon/browserconfig.xml diff --git a/docs/src/.vuepress/public/assets/images/favicon/favicon-16x16.png b/docs/docs/.vuepress/public/assets/images/favicon/favicon-16x16.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/favicon-16x16.png rename to docs/docs/.vuepress/public/assets/images/favicon/favicon-16x16.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/favicon-256x256.png b/docs/docs/.vuepress/public/assets/images/favicon/favicon-256x256.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/favicon-256x256.png rename to docs/docs/.vuepress/public/assets/images/favicon/favicon-256x256.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/favicon-32x32.png b/docs/docs/.vuepress/public/assets/images/favicon/favicon-32x32.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/favicon-32x32.png rename to docs/docs/.vuepress/public/assets/images/favicon/favicon-32x32.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/favicon-96x96.png b/docs/docs/.vuepress/public/assets/images/favicon/favicon-96x96.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/favicon-96x96.png rename to docs/docs/.vuepress/public/assets/images/favicon/favicon-96x96.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/favicon.ico b/docs/docs/.vuepress/public/assets/images/favicon/favicon.ico similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/favicon.ico rename to docs/docs/.vuepress/public/assets/images/favicon/favicon.ico diff --git a/docs/src/.vuepress/public/assets/images/favicon/manifest.json b/docs/docs/.vuepress/public/assets/images/favicon/manifest.json similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/manifest.json rename to docs/docs/.vuepress/public/assets/images/favicon/manifest.json diff --git a/docs/src/.vuepress/public/assets/images/favicon/ms-icon-144x144.png b/docs/docs/.vuepress/public/assets/images/favicon/ms-icon-144x144.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/ms-icon-144x144.png rename to docs/docs/.vuepress/public/assets/images/favicon/ms-icon-144x144.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/ms-icon-150x150.png b/docs/docs/.vuepress/public/assets/images/favicon/ms-icon-150x150.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/ms-icon-150x150.png rename to docs/docs/.vuepress/public/assets/images/favicon/ms-icon-150x150.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/ms-icon-310x310.png b/docs/docs/.vuepress/public/assets/images/favicon/ms-icon-310x310.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/ms-icon-310x310.png rename to docs/docs/.vuepress/public/assets/images/favicon/ms-icon-310x310.png diff --git a/docs/src/.vuepress/public/assets/images/favicon/ms-icon-70x70.png b/docs/docs/.vuepress/public/assets/images/favicon/ms-icon-70x70.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/favicon/ms-icon-70x70.png rename to docs/docs/.vuepress/public/assets/images/favicon/ms-icon-70x70.png diff --git a/docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-medium.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-medium.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-medium.png rename to docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-medium.png diff --git a/docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-small.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-small.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-small.png rename to docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full-small.png diff --git a/docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-full.png rename to docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-full.png diff --git a/docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-baseline.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-baseline.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-baseline.png rename to docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-baseline.png diff --git a/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text-dark-mode.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text-dark-mode.png new file mode 100644 index 000000000..824a5c5f8 Binary files /dev/null and b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text-dark-mode.png differ diff --git a/docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text.png b/docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text.png rename to docs/docs/.vuepress/public/assets/images/logo/cassandre-trading-bot-without-text.png diff --git a/docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-github-profile.png b/docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-github-profile.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-github-profile.png rename to docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-github-profile.png diff --git a/docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-github.png b/docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-github.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-github.png rename to docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-github.png diff --git a/docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-open-graph.png b/docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-open-graph.png similarity index 100% rename from docs/src/.vuepress/public/assets/images/social/cassandre-trading-bot-open-graph.png rename to docs/docs/.vuepress/public/assets/images/social/cassandre-trading-bot-open-graph.png diff --git a/docs/src/.vuepress/public/assets/src/deployment.yml b/docs/docs/.vuepress/public/assets/src/deployment.yml similarity index 100% rename from docs/src/.vuepress/public/assets/src/deployment.yml rename to docs/docs/.vuepress/public/assets/src/deployment.yml diff --git a/docs/src/.vuepress/public/assets/src/docker-compose.yml b/docs/docs/.vuepress/public/assets/src/docker-compose.yml similarity index 100% rename from docs/src/.vuepress/public/assets/src/docker-compose.yml rename to docs/docs/.vuepress/public/assets/src/docker-compose.yml diff --git a/docs/docs/README.md b/docs/docs/README.md new file mode 100644 index 000000000..f90c3cb28 --- /dev/null +++ b/docs/docs/README.md @@ -0,0 +1,51 @@ +--- +home: true +title: Cassandre - Create your java crypto trading bot in minutes +heroImage: assets/images/logo/cassandre-trading-bot-without-text.png + +actions: +- text: Get Started + link: /learn/quickstart + type: primary +- text: View on GitHub + link: https://github.com/cassandre-tech/cassandre-trading-bot + type: secondary + +features: +- title: Get into trading with minimum fuss + details: Available as a Spring boot starter, Cassandre takes care of exchange connection, accounts, orders, trades, and positions, so you can focus on building your strategy. +- title: Create your strategy in minutes + details: Just code when you want to create short/long positions, set the rules, and we take care of everything (buying, selling, rules management, orders, trades, and tickers). +- title: Several exchanges supported + details: Cassandre uses XChange library to connect to multiple exchanges. We test each Cassandre releases with Kucoin, Coinbase & Binance to be sure it works for you. +- title: Dry mode + details: We provide a dry mode to simulate a virtual exchange replying to your orders, so you can easily test your strategy. This way, you can simulate your gains/loss over a period of time. +- title: Backtesting + details: We provide a spring boot starter to backtest your bot on historical data. With this, during tests, Cassandre will import your data and push them to your strategy. +- title: Technical Analysis support + details: Cassandre provides a specific class (BasicTa4jCassandreStrategy) to help you build a strategy based on the open source technical analysis library ta4j. +footer: GPL-3.0 License | Copyright © Stéphane Traumat +--- + +### As Easy as 1, 2, 3 + + + + +```bash +# Create a simple project with our archetype +mvn archetype:generate \ +-DarchetypeGroupId=tech.cassandre.trading.bot \ +-DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ +-DarchetypeVersion=CASSANDRE_LATEST_RELEASE \ +-DgroupId=com.example \ +-DartifactId=my-bot \ +-Dversion=1.0-SNAPSHOT \ +-Dpackage=com.example + +# Runs unit tests +mvn -f my-bot/pom.xml test +``` + + + \ No newline at end of file diff --git a/docs/src/deploy-and-run/docker.md b/docs/docs/deploy-and-run/docker.md similarity index 98% rename from docs/src/deploy-and-run/docker.md rename to docs/docs/deploy-and-run/docker.md index 6791de131..aee4ac00f 100644 --- a/docs/src/deploy-and-run/docker.md +++ b/docs/docs/deploy-and-run/docker.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Deploy and run Cassandre with Docker +description: Learn how to use Docker to deploy PostgreSQL and Cassandre easily +--- # Deploy & run with Docker ## Server installation diff --git a/docs/src/deploy-and-run/images/qovery-application-type-choice.png b/docs/docs/deploy-and-run/images/qovery-application-type-choice.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-application-type-choice.png rename to docs/docs/deploy-and-run/images/qovery-application-type-choice.png diff --git a/docs/src/deploy-and-run/images/qovery-configure-project.png b/docs/docs/deploy-and-run/images/qovery-configure-project.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-configure-project.png rename to docs/docs/deploy-and-run/images/qovery-configure-project.png diff --git a/docs/src/deploy-and-run/images/qovery-create-application.png b/docs/docs/deploy-and-run/images/qovery-create-application.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-create-application.png rename to docs/docs/deploy-and-run/images/qovery-create-application.png diff --git a/docs/src/deploy-and-run/images/qovery-create-project.png b/docs/docs/deploy-and-run/images/qovery-create-project.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-create-project.png rename to docs/docs/deploy-and-run/images/qovery-create-project.png diff --git a/docs/src/deploy-and-run/images/qovery-database-choice.png b/docs/docs/deploy-and-run/images/qovery-database-choice.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-database-choice.png rename to docs/docs/deploy-and-run/images/qovery-database-choice.png diff --git a/docs/src/deploy-and-run/images/qovery-database-configuration.png b/docs/docs/deploy-and-run/images/qovery-database-configuration.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-database-configuration.png rename to docs/docs/deploy-and-run/images/qovery-database-configuration.png diff --git a/docs/src/deploy-and-run/images/qovery-deployment-summary.png b/docs/docs/deploy-and-run/images/qovery-deployment-summary.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-deployment-summary.png rename to docs/docs/deploy-and-run/images/qovery-deployment-summary.png diff --git a/docs/src/deploy-and-run/images/qovery-select-github-project.png b/docs/docs/deploy-and-run/images/qovery-select-github-project.png similarity index 100% rename from docs/src/deploy-and-run/images/qovery-select-github-project.png rename to docs/docs/deploy-and-run/images/qovery-select-github-project.png diff --git a/docs/src/learn/architecture.md b/docs/docs/learn/architecture.md similarity index 52% rename from docs/src/learn/architecture.md rename to docs/docs/learn/architecture.md index 95c3416d6..634694591 100644 --- a/docs/src/learn/architecture.md +++ b/docs/docs/learn/architecture.md @@ -1,2 +1,7 @@ +--- +lang: en-US +title: Architecture +description: Learn Cassandre architecture +--- # Architecture ![Cassandre architecture](./images/cassandre-trading-bot-architecture.png) diff --git a/docs/docs/learn/database-structure.md b/docs/docs/learn/database-structure.md new file mode 100644 index 000000000..9a5049231 --- /dev/null +++ b/docs/docs/learn/database-structure.md @@ -0,0 +1,7 @@ +--- +lang: en-US +title: Database structure +description: Learn how Cassandre data is structured +--- +# Database structure +![Database structure](./images/cassandre-trading-bot-database.png) diff --git a/docs/src/learn/dry-mode-and-backtesting.md b/docs/docs/learn/dry-mode-and-backtesting.md similarity index 85% rename from docs/src/learn/dry-mode-and-backtesting.md rename to docs/docs/learn/dry-mode-and-backtesting.md index fb6de6a03..395f75944 100644 --- a/docs/src/learn/dry-mode-and-backtesting.md +++ b/docs/docs/learn/dry-mode-and-backtesting.md @@ -1,7 +1,12 @@ +--- +lang: en-US +title: Dry mode & backtesting +description: Learn how to simulate a virtual exchange and import historical data to test your strategy gains +--- # Dry mode & backtesting ## Dry mode -Cassandre provides a dry mode allowing you to simulate exchange interactions. You can enable it by setting the parameter `cassandre.trading.bot.exchange.modes.dry` to `true` in `src/main/resources/application.properties.` +Cassandre provides a dry mode allowing you to simulate a virtual exchange and its replies. You can enable it by setting the parameter `cassandre.trading.bot.exchange.modes.dry` to `true` in `src/main/resources/application.properties.` Cassandre will emulate valid exchange replies to your orders and will increase/decrease your virtual account. This way, you can test your strategy, see the gains you will make, and validate you have the results you expect. @@ -48,8 +53,6 @@ Edit your `pom.xml` file and add this dependency : ``` -[![Maven Central](https://img.shields.io/maven-central/v/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-starter.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22) - Now, we need to generate the data we want to use during the JUnit tests. We can use the [Kucoin API](https://docs.kucoin.com/#get-klines); to do so, run this on the command line : ```bash diff --git a/docs/docs/learn/exchange-connection-configuration.md b/docs/docs/learn/exchange-connection-configuration.md new file mode 100644 index 000000000..2cc253d69 --- /dev/null +++ b/docs/docs/learn/exchange-connection-configuration.md @@ -0,0 +1,84 @@ +--- +lang: en-US +title: Configure exchange connection +description: Learn how to configure Cassandre to connect to a specific exchange (kucoin, Binance, Coinbase...) +--- +# Configure exchange connection + +## How does it works? +There are two steps to configure an exchange connection in Cassandre. + +Cassandre uses [XChange](https://github.com/knowm/XChange), a Java library providing a streamlined API for interacting with 60+ Bitcoin and Altcoin exchanges. The first thing you have to do is to find the XChange library suited for the Exchange you chose. The list is [here](https://search.maven.org/search?q=org.knowm.xchange). + +For example, for a Coinbase connection, you have to add this to your `pom.xml`: +```xml + + org.knowm.xchange + xchange-coinbasepro + 5.0.12 + +``` + +The second step is to update those properties in your `application.properties`: +```properties +# Exchange configuration. +cassandre.trading.bot.exchange.driver-class-name=org.knowm.xchange.coinbasepro.CoinbaseProExchange +cassandre.trading.bot.exchange.username=kucoin.cassandre.test@gmail.com +cassandre.trading.bot.exchange.passphrase=cassandre +cassandre.trading.bot.exchange.key=6054ad25365ac6000689a998 +cassandre.trading.bot.exchange.secret=af080d55-afe3-47c9-8ec1-4b479fbcc5e7 +``` + +For `cassandre.trading.bot.exchange.driver-class-name`, you have to set the main class inside the XChange library. + +The other parameters `username`, `passphrase`, `key` and`secret` are authentication parameters given by the Exchange when you will create your API access in your account. + +## Configuration examples + +### Kucoin +Add this dependency to your ̀pom.xml`: +```xml + + org.knowm.xchange + xchange-kucoin + 5.0.12 + +``` +and update your `application.properties`: +```properties +cassandre.trading.bot.exchange.driver-class-name=kucoin +``` + +### Coinbase +Add this dependency to your ̀pom.xml`: +```xml + + org.knowm.xchange + xchange-coinbasepro + 5.0.12 + +``` +and update your `application.properties`: +```properties +cassandre.trading.bot.exchange.driver-class-name=org.knowm.xchange.coinbasepro.CoinbaseProExchange +``` + +### Binance +Add this dependency to your ̀pom.xml`: +```xml + + org.knowm.xchange + xchange-binance + 5.0.12 + +``` +and update your `application.properties`: +```properties +cassandre.trading.bot.exchange.driver-class-name=org.knowm.xchange.binance.BinanceExchange +``` +On Binance, you should not ask for data too often, or you will get a `Way too much request weight used` error, use those parameters in your `application.properties`: +```properties +cassandre.trading.bot.exchange.rates.account=PT30S +cassandre.trading.bot.exchange.rates.ticker=PT30S +cassandre.trading.bot.exchange.rates.trade=PT30S +``` diff --git a/docs/docs/learn/graphql-api-documentation/.keep b/docs/docs/learn/graphql-api-documentation/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/docs/learn/graphql-api-documentation/README.md b/docs/docs/learn/graphql-api-documentation/README.md new file mode 100644 index 000000000..fe2215b46 --- /dev/null +++ b/docs/docs/learn/graphql-api-documentation/README.md @@ -0,0 +1,9 @@ +# API Reference + +View reference documentation to learn about the data types available in your GraphQL API schema. + + +- [Query](queries.md) +- [Objects](objects.md) +- [Enums](enums.md) +- [Scalars](scalars.md) \ No newline at end of file diff --git a/docs/docs/learn/graphql-api-documentation/enums.md b/docs/docs/learn/graphql-api-documentation/enums.md new file mode 100644 index 000000000..2168cd123 --- /dev/null +++ b/docs/docs/learn/graphql-api-documentation/enums.md @@ -0,0 +1,126 @@ +# Enums + +### About enums + +[Enums](https://graphql.github.io/graphql-spec/June2018/#sec-Enums) represent possible sets of values for a field. + +### OrderType + + + + + + + + + + + + + + + + +
ValueDescription
ASK

Selling.

BID

Buying.

+ +--- + +### PositionStatus + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
CLOSED

Closed - the sell order has been accepted.

CLOSING

Closing - a sell order has been made but not yet completed.

CLOSING_FAILURE

Closing failure - the sell order did not succeed.

OPENED

Opened - the buy order has been accepted.

OPENING

Opening - a position has been created, a buy order has been made but not yet completed.

OPENING_FAILURE

Opening failure - a position has been created, but the buy order did not succeed.

+ +--- + +### PositionType + + + + + + + + + + + + + + + + +
ValueDescription
LONG

Long position is nothing but buying share and selling them later for more.

SHORT

Short position is nothing but selling share and buying back later for less.

+ +--- + +### StrategyType + + + + + + + + + + + + + + + + +
ValueDescription
BASIC_STRATEGY

Basic strategy.

BASIC_TA4J_STRATEGY

Basic Ta4j strategy.

+ +--- + +### TradeType + + + + + + + + + + + + + + + + +
ValueDescription
ASK

Selling.

BID

Buying.

+ +--- \ No newline at end of file diff --git a/docs/docs/learn/graphql-api-documentation/objects.md b/docs/docs/learn/graphql-api-documentation/objects.md new file mode 100644 index 000000000..d5d492c25 --- /dev/null +++ b/docs/docs/learn/graphql-api-documentation/objects.md @@ -0,0 +1,453 @@ +# Objects + +### About objects + +[Objects](https://graphql.github.io/graphql-spec/June2018/#sec-Objects) in GraphQL represent the resources you can access. An object can contain a list of fields, which are specifically typed. + +### Account + +

User account.

+ +#### Fields + + + + + + + + + + + + + + + + + + +
NameDescription
accountId (String!)

A unique identifier for this account.

balances ([Balance])

Represents the different balances for each currency owned by the account.

name (String)

A descriptive name for this account. Defaults has the same value than accountId.

+ +--- + +### Balance + +

Balance of a user account.

+ +#### Fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
available (BigDecimal)

Returns the amount of the currency in this balance that is available to trade.

borrowed (BigDecimal)

Returns the borrowed amount of the available currency in this balance that must be repaid.

currency (Currency!)

Currency.

depositing (BigDecimal)

Returns the amount of the currency in this balance that is locked in the deposit.

frozen (BigDecimal)

Returns the frozen amount of the currency in this balance that is locked in trading.

loaned (BigDecimal)

Returns the loaned amount of the total currency in this balance that will be returned.

total (BigDecimal)

Returns the total amount of the currency in this balance.

withdrawing (BigDecimal)

Returns the amount of the currency in this balance that is locked in withdrawal.

+ +--- + +### Configuration + +

Server configuration.

+ +#### Fields + + + + + + + + + + +
NameDescription
apiVersion (String!)

API Version.

+ +--- + +### Currency + +

Currency.

+ +#### Fields + + + + + + + + + + +
NameDescription
code (ID!)

Code.

+ +--- + +### CurrencyAmount + +

Currency amount (amount value and currency).

+ +#### Fields + + + + + + + + + + + + + + +
NameDescription
currency (Currency)

Currency.

value (BigDecimal)

Amount value.

+ +--- + +### CurrencyPair + +

Currency pair for trading.

+ +#### Fields + + + + + + + + + + + + + + +
NameDescription
baseCurrency (Currency!)

The base currency is the first currency appearing in a currency pair quotation.

quoteCurrency (Currency!)

The quote currency is the second currency appearing in a currency pair quotation.

+ +--- + +### Gain + +

Gain.

+ +#### Fields + + + + + + + + + + + + + + + + + + +
NameDescription
amount (CurrencyAmount)

Gain made (amount).

fees (CurrencyAmount)

Fees.

percentage (Float)

Gain made (percentage).

+ +--- + +### Order + +

An order is a request by an investor to buy or sell.

+ +#### Fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
amount (CurrencyAmount!)

Amount to be ordered / amount that was ordered.

averagePrice (CurrencyAmount)

Weighted Average price of the fills in the order.

cumulativeAmount (CurrencyAmount)

Amount to be ordered / amount that has been matched against order on the order book/filled.

currencyPair (CurrencyPair!)

Currency pair.

id (Int!)

Technical ID.

leverage (String)

The leverage to use for margin related to this order.

limitPrice (CurrencyAmount)

Limit price.

marketPrice (CurrencyAmount)

Market price - The price Cassandre had when the order was created.

orderId (String!)

An identifier set by the exchange that uniquely identifies the order.

status (String)

Order status.

strategy (Strategy!)

The strategy that created the order.

timestamp (DateTime)

The timestamp of the order.

trades ([Trade])

All trades related to order.

type (OrderType!)

Order type i.e. bid (buy) or ask (sell).

userReference (String)

An identifier provided by the user on placement that uniquely identifies the order.

+ +--- + +### Position + +

A position is the amount of a security, commodity or currency which is owned by an individual, dealer, institution, or other fiscal entity.

+ +#### Fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
amount (CurrencyAmount!)

Position amount.

closingOrder (Order)

The order created to close the position.

currencyPair (CurrencyPair!)

Currency pair.

forceClosing (Boolean!)

Indicates that the position must be closed no matter the rules.

gain (Gain)

If closed, returns the gain made.

highestCalculatedGain (Gain)

Highest calculated gain.

id (Int!)

Technical ID.

latestCalculatedGain (Gain)

Latest calculated gain.

lowestCalculatedGain (Gain)

Lowest calculated gain.

openingOrder (Order!)

The order created to open the position.

positionId (Int!)

An identifier that uniquely identifies the position.

rules (PositionRules!)

Position rules.

status (PositionStatus)

Position status.

strategy (Strategy!)

The strategy that created the position.

type (PositionType!)

Position type (Long or Short).

+ +--- + +### PositionRules + +

Position rules is used to know when cassandre should close a position.

+ +#### Fields + + + + + + + + + + + + + + +
NameDescription
stopGainPercentage (Float)

Stop gain percentage.

stopLossPercentage (Float)

Stop loss percentage.

+ +--- + +### Strategy + +

Strategies.

+ +#### Fields + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
id (Int!)

Technical ID.

name (String)

Strategy name - Comes from the Java annotation.

strategyId (String!)

An identifier that uniquely identifies the strategy - Comes from the Java annotation.

type (StrategyType!)

Strategy type - Basic or Ta4j.

+ +--- + +### Trade + +

A trade is the action of buying and selling (linked to an order).

+ +#### Fields + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
amount (CurrencyAmount!)

Amount to be ordered / amount that was ordered.

currencyPair (CurrencyPair!)

Currency pair.

fee (CurrencyAmount)

The fee that was charged by the exchange for this trade.

id (Int!)

Technical ID.

order (Order)

The order responsible for this trade.

orderId (String!)

The order id of the order responsible for this trade.

price (CurrencyAmount)

The price.

timestamp (DateTime)

The timestamp of the trade.

tradeId (String!)

An identifier set by the exchange that uniquely identifies the trade.

type (TradeType!)

Trade type i.e. bid (buy) or ask (sell).

userReference (String)

An identifier provided by the user on placement that uniquely identifies the order.

+ +--- \ No newline at end of file diff --git a/docs/docs/learn/graphql-api-documentation/queries.md b/docs/docs/learn/graphql-api-documentation/queries.md new file mode 100644 index 000000000..e399f6342 --- /dev/null +++ b/docs/docs/learn/graphql-api-documentation/queries.md @@ -0,0 +1,223 @@ +# Queries + +### About queries + + + +### accountByAccountId + +#### Type: [Account](objects.md#account) + +Returns the account with the corresponding id. + +#### Arguments + +| Name | Description | +|------|-------------| +| accountId ([String](scalars.md#string)) | | + +--- + +### accounts + +#### Type: [[Account]](objects.md#account) + +Retours all the accounts. + +--- + +### configuration + +#### Type: [Configuration](objects.md#configuration) + +Returns configuration. + +--- + +### order + +#### Type: [Order](objects.md#order) + +Returns the order with the corresponding id. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | + +--- + +### orderByOrderId + +#### Type: [Order](objects.md#order) + +Returns the order with the corresponding orderId. + +#### Arguments + +| Name | Description | +|------|-------------| +| orderId ([String](scalars.md#string)) | | + +--- + +### orders + +#### Type: [[Order]](objects.md#order) + +Returns all the orders. + +--- + +### position + +#### Type: [Position](objects.md#position) + +Returns the position with the corresponding id. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | + +--- + +### positions + +#### Type: [[Position]](objects.md#position) + +Returns all the positions + +--- + +### positionsByStrategy + +#### Type: [[Position]](objects.md#position) + +Returns all the positions of the specified strategy. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | + +--- + +### positionsByStrategyAndStatus + +#### Type: [[Position]](objects.md#position) + +Returns all the positions of the specified strategy and a certain status. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | +| status ([PositionStatus](enums.md#positionstatus)) | | + +--- + +### positionsByStrategyId + +#### Type: [[Position]](objects.md#position) + +Returns all the positions of the specified strategy. + +#### Arguments + +| Name | Description | +|------|-------------| +| strategyId ([String](scalars.md#string)) | | + +--- + +### positionsByStrategyIdAndStatus + +#### Type: [[Position]](objects.md#position) + +Returns all the positions of the specified strategy and a certain status. + +#### Arguments + +| Name | Description | +|------|-------------| +| strategyId ([String](scalars.md#string)) | | +| status ([PositionStatus](enums.md#positionstatus)) | | + +--- + +### strategies + +#### Type: [[Strategy]](objects.md#strategy) + +Returns all the strategies. + +--- + +### strategy + +#### Type: [Strategy](objects.md#strategy) + +Returns the strategy with the corresponding id. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | + +--- + +### strategyByStrategyId + +#### Type: [Strategy](objects.md#strategy) + +Returns the strategy with the corresponding strategyId. + +#### Arguments + +| Name | Description | +|------|-------------| +| strategyId ([String](scalars.md#string)) | | + +--- + +### trade + +#### Type: [Trade](objects.md#trade) + +Returns the trade with the corresponding id. + +#### Arguments + +| Name | Description | +|------|-------------| +| id ([Int](scalars.md#int)) | | + +--- + +### tradeByTradeId + +#### Type: [Trade](objects.md#trade) + +Returns the trade with the corresponding tradeId. + +#### Arguments + +| Name | Description | +|------|-------------| +| tradeId ([String](scalars.md#string)) | | + +--- + +### trades + +#### Type: [[Trade]](objects.md#trade) + +Returns all the trades. + +--- \ No newline at end of file diff --git a/docs/docs/learn/graphql-api-documentation/scalars.md b/docs/docs/learn/graphql-api-documentation/scalars.md new file mode 100644 index 000000000..75aa763df --- /dev/null +++ b/docs/docs/learn/graphql-api-documentation/scalars.md @@ -0,0 +1,49 @@ +# Scalars + +### About scalars + +[Scalars](https://graphql.github.io/graphql-spec/June2018/#sec-Scalars) are primitive values: `Int`, `Float`, `String`, `Boolean`, or `ID`. + +When calling the GraphQL API, you must specify nested subfields until you return only scalars. + +### BigDecimal + + + +--- + +### Boolean + +

The Boolean scalar type represents true or false.

+ +--- + +### DateTime + + + +--- + +### Float + +

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

+ +--- + +### ID + +

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

+ +--- + +### Int + +

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.

+ +--- + +### String + +

The String scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

+ +--- \ No newline at end of file diff --git a/docs/docs/learn/graphql-api.md b/docs/docs/learn/graphql-api.md new file mode 100644 index 000000000..b8bffc5ef --- /dev/null +++ b/docs/docs/learn/graphql-api.md @@ -0,0 +1,35 @@ +--- +lang: en-US +title: GraphQL API +description: Learn how to add our GraphQL API to your bot to query your data from third-party software +--- +# GraphQL API + +## Overview +Cassandre GraphQL API allows you to query your data (balances, strategies, orders, trades and positions). + +## Installation +To deploy the GraphQL API on your bot, just add this spring boot starter to your pom: +```xml + + tech.cassandre.trading.bot + cassandre-trading-bot-spring-boot-starter-api-graphql + CASSANDRE_LATEST_RELEASE + +``` + +## Access the API with GraphiQL +Start your bot and open a browser to [http://localhost:8080/graphiql](http://localhost:8080/graphiql). GraphiQL is a query editor that comes out of the box with the [DGS framework](https://netflix.github.io/dgs/) we are using. + +For example, you can try to enter this query to display all your strategies: +``` +query { + strategies{ strategyId name } +} +``` + +## Secure your API +To secure your API with a key, add this property: `cassandre.trading.bot.api.graphql.key` in your `applications.properties`. + +## API Documentation +You can view the API documentation at [this address](graphql-api-documentation). \ No newline at end of file diff --git a/docs/src/learn/images/cassandre-trading-bot-architecture.png b/docs/docs/learn/images/cassandre-trading-bot-architecture.png similarity index 100% rename from docs/src/learn/images/cassandre-trading-bot-architecture.png rename to docs/docs/learn/images/cassandre-trading-bot-architecture.png diff --git a/docs/src/learn/images/cassandre-trading-bot-database.png b/docs/docs/learn/images/cassandre-trading-bot-database.png similarity index 100% rename from docs/src/learn/images/cassandre-trading-bot-database.png rename to docs/docs/learn/images/cassandre-trading-bot-database.png diff --git a/docs/src/learn/images/technical_analysis_chart.png b/docs/docs/learn/images/technical_analysis_chart.png similarity index 100% rename from docs/src/learn/images/technical_analysis_chart.png rename to docs/docs/learn/images/technical_analysis_chart.png diff --git a/docs/src/learn/import-historical-data.md b/docs/docs/learn/import-historical-data.md similarity index 50% rename from docs/src/learn/import-historical-data.md rename to docs/docs/learn/import-historical-data.md index 773e3a30d..0d317ebf4 100644 --- a/docs/src/learn/import-historical-data.md +++ b/docs/docs/learn/import-historical-data.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Import historical data +description: Learn how to use import historical data when your trading bot start and use them in your strategy +--- # Import historical data ## Overview @@ -15,9 +20,9 @@ CURRENCY_PAIR,OPEN,LAST,BID,ASK,HIGH,LOW,VWAP,VOLUME,QUOTE_VOLUME,BID_SIZE,ASK_S ``` ## When to initialize data? -In you strategy, you should implement the `initialize()` method. This method is executed by Cassandre before any other data (tickers, orders, trades...) is pushed to the strategy. +In you strategy, you should implement the [initialize()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#initialize()) method. This method is executed by Cassandre before any other data (tickers, orders, trades...) is pushed to the strategy. ## Access your data in your strategy In your strategy, you can access the data with two methods: - * `List getImportedTickers()`. - * `List getImportedTickers(CurrencyPairDTO currencyPairDTO)`. \ No newline at end of file + * [getImportedTickers()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#getImportedTickers()). + * [getImportedTickers(CurrencyPairDTO currencyPairDTO)](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#getImportedTickers(tech.cassandre.trading.bot.dto.util.CurrencyPairDTO)). \ No newline at end of file diff --git a/docs/src/learn/position-management.md b/docs/docs/learn/position-management.md similarity index 96% rename from docs/src/learn/position-management.md rename to docs/docs/learn/position-management.md index 101138e2c..68f54d8eb 100644 --- a/docs/src/learn/position-management.md +++ b/docs/docs/learn/position-management.md @@ -1,5 +1,10 @@ +--- +lang: en-US +title: Position management +description: Learn how to use Cassandre positions to manage your trades easily +--- # Position management -Cassandre provides a class to manage your positions automatically. +Cassandre provides a simple way to manage your positions automatically. ## Long position In your strategy, you can create a long position with the [createLongPosition()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#createLongPosition%28tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal,tech.cassandre.trading.bot.dto.position.PositionRulesDTO%29) method. diff --git a/docs/src/learn/quickstart.md b/docs/docs/learn/quickstart.md similarity index 92% rename from docs/src/learn/quickstart.md rename to docs/docs/learn/quickstart.md index 7dc6413e8..062d9762e 100644 --- a/docs/src/learn/quickstart.md +++ b/docs/docs/learn/quickstart.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Quickstart your trading bot +description: Learn how to create your own crypto trading bot in few simple steps +--- # Quickstart ::: tip @@ -5,27 +10,18 @@ If you are new to trading, you can read our tutorial "[Trading basics](../ressou ::: ## Create your project -If you don't have an existing spring boot project, you can use our [maven archetype](https://search.maven.org/search?q=a:cassandre-trading-bot-spring-boot-starter-basic-archetype) to generate one : +If you don't have an existing spring boot project, you can use our [maven archetype](https://search.maven.org/search?q=a:cassandre-trading-bot-spring-boot-starter-basic-archetype) to generate one: ```bash mvn archetype:generate \ -DarchetypeGroupId=tech.cassandre.trading.bot \ -DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ --DarchetypeVersion=CASSANDRE_LATEST_RELEASE +-DarchetypeVersion=CASSANDRE_LATEST_RELEASE \ +-DgroupId=com.mycompany.app \ +-DartifactId=my-app \ +-Dversion=1.0-SNAPSHOT \ +-Dpackage=com.mycompany.app ``` - -[![Maven Central](https://img.shields.io/maven-central/v/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-starter.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22) - -It will ask for the following parameters: - -| Parameters | Description | Example values | -| :--- | :--- | :--- | -| groupId | The id of the project's group | com.mycompany.app | -| artifactId | The id of the artifact (project) | my-app | -| version | The version of the artifact under the specified group | 1.0-SNAPSHOT | -| package | The java package | com.mycompany.app | - -The created project will have the following structure and files : - +The created project will have the following structure and files: ``` my-app/ ├── pom.xml @@ -56,7 +52,7 @@ my-app/ ``` ## Review configuration -Your bot configuration is located in `src/main/resources/application.properties` : +Your bot configuration is located in `src/main/resources/application.properties`: ```properties # @@ -136,7 +132,7 @@ public final class SimpleStrategy extends BasicCassandreStrategy { @Override public Set getRequestedCurrencyPairs() { - // We only ask about ETC/BTC (Base currency : BTC / Quote currency : USDT). + // We only ask BTC/USDT tickers (Base currency : BTC / Quote currency : USDT). return Set.of(new CurrencyPairDTO(BTC, USDT)); } @@ -194,10 +190,9 @@ public final class SimpleStrategy extends BasicCassandreStrategy { A Cassandre strategy is a class annotated with [@CassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategy.html) and extending [BasicCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicCassandreStrategy.html) or [BasicTa4jCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html). -This is how it works : - -* In [getRequestedCurrencyPairs()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getRequestedCurrencyPairs%28%29), you give to Cassandre the list of currency pairs updates you want to receive from the exchange. -* On the exchange, you usually have several accounts, and Cassandre needs to know which one of your accounts is the trading one. To do so, you have to implement the [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getTradeAccount%28java.util.Set%29) method, which gives you as a parameter the list of accounts you own, and from that list, you have to return the one you use for trading. +This is how it works: +* In [getRequestedCurrencyPairs()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getRequestedCurrencyPairs%28%29), you return the list of currency pairs tickers you want to receive from the exchange. +* On the exchange, you usually have several accounts, and Cassandre needs to know which one of your accounts is the trading one. To do so, you have to implement the [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getTradeAccount%28java.util.Set%29) method, which gives you as a parameter the list of accounts you own on the exchange, and from that list, you have to return the one you use for trading. * If there is a change in your account data, [onAccountsUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onAccountsUpdates(java.util.Map)) will be called. * When new tickers are available, [onTickersUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onTickersUpdates(java.util.Map)) will be called. * If there is a change in your orders, [onOrdersUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onOrdersUpdates(java.util.Map)) will be called. @@ -206,7 +201,7 @@ This is how it works : * If there is a change in your position status, [onPositionsStatusUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onPositionsStatusUpdates(java.util.Map)) will be called. ## Manage orders and positions -You can create an order like this : +You can create an order this way: ```java @Override @@ -215,7 +210,7 @@ public final void onTickersUpdates(final Map tickers } ``` -This is the list of available methods : +This is the list of available methods to manage orders: * [createBuyMarketOrder()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#createBuyMarketOrder%28tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal%29). * [createSellMarketOrder()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#createSellMarketOrder%28tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal%29). * [createBuyLimitOrder()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#createBuyLimitOrder%28tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal,java.math.BigDecimal%29). @@ -225,37 +220,37 @@ This is the list of available methods : Inside your strategy, you can call [canBuy()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#canBuy%28tech.cassandre.trading.bot.dto.user.AccountDTO,tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal%29) and [canSell()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#canSell%28tech.cassandre.trading.bot.dto.util.CurrencyDTO,java.math.BigDecimal%29) methods to see if your account has enough money to buy or sell assets. ::: -Cassandre trading bot also provides positions to manage your trade automatically: +Cassandre trading bot also provides positions to manage your trading automatically: ```java -// Create rule. +// Create rules. PositionRulesDTO rules = PositionRulesDTO.builder() .stopGainPercentage(10) .stopLossPercentage(5) .build(); -// Create position. +// Create a position. createLongPosition(new CurrencyPairDTO(BTC, USDT), new BigDecimal("0,001"), rules); ``` -First, we created a [rule](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/dto/position/PositionRulesDTO.html) saying this position should be closed if the gain is more than 10% or if the loss is more than 5%. +First, we created a [rule](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/dto/position/PositionRulesDTO.html) saying this position should be closed if the calculated gain is more than 10% or if the loss is more than 5%. Then we called the [createLongPosition()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#createLongPosition(tech.cassandre.trading.bot.dto.util.CurrencyPairDTO,java.math.BigDecimal,tech.cassandre.trading.bot.dto.position.PositionRulesDTO)) method. This will automatically create a buy order. From now, for every ticker received, Cassandre will check the gain or loss made on this position; if it triggers one of the rules, Cassandre will automatically create a sell order to close the position. ::: tip -You can learn more about positions in the [Position chapter](./position-management.md). +You can learn more about positions in the [position chapter](./position-management.md). ::: ## Run the bot and the strategy -In the project folder, run : +In the project folder, run: ```bash mvn spring-boot:run ``` -The logs should display something like this : +The logs should display something like this: ```bash . ____ _ __ _ _ @@ -332,3 +327,7 @@ Received information about an account : AccountDTO(accountId=main, name=main, fe Received information about an account : AccountDTO(accountId=trade, name=trade, features=[], balances={BTC=BalanceDTO(currency=BTC, total=null, available=1, frozen=null, loaned=null, borrowed=null, withdrawing=null, depositing=null), USDT=BalanceDTO(currency=USDT, total=null, available=100000, frozen=null, loaned=null, borrowed=null, withdrawing=null, depositing=null), ETH=BalanceDTO(currency=ETH, total=null, available=10, frozen=null, loaned=null, borrowed=null, withdrawing=null, depositing=null)}) Received information about a ticker : TickerDTO(currencyPair=BTC/USDT, open=null, last=37072.9, bid=37070.3, ask=37072.9, high=37250.3, low=34400, vwap=null, volume=74075.19293933, quoteVolume=2677417785.328956311, bidSize=null, askSize=null, timestamp=2021-02-03T19:06:08.055+01:00[Europe/Paris]) ``` + +::: tip +Kucoin sandbox is having some issues right now. You should create your own exchange account and configure Cassandre accordingly. +::: \ No newline at end of file diff --git a/docs/src/learn/technical-analysis.md b/docs/docs/learn/technical-analysis.md similarity index 95% rename from docs/src/learn/technical-analysis.md rename to docs/docs/learn/technical-analysis.md index f8809f395..09fc594d7 100644 --- a/docs/src/learn/technical-analysis.md +++ b/docs/docs/learn/technical-analysis.md @@ -1,9 +1,14 @@ +--- +lang: en-US +title: Technical analysis with ta4j +description: Learn how to use technical analysis in Cassandre with the ta4j library +--- # Technical analysis ## Overview ::: tip -We learned the basics of technical analysis thanks to [Technical Analysis For Dummies](https://amzn.to/38TWaQm). +We learned the basics of technical analysis thanks to the book [technical Analysis For Dummies](https://amzn.to/38TWaQm). ::: ### Introduction @@ -88,8 +93,6 @@ mvn -B archetype:generate -DarchetypeGroupId=tech.cassandre.trading.bot \ -Dpackage=com.example ``` -[![Maven Central](https://img.shields.io/maven-central/v/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-starter.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22) - The created project is a spring boot project with the following structure : ``` @@ -241,8 +244,6 @@ Edit your `pom.xml` file and add : ``` -[![Maven Central](https://img.shields.io/maven-central/v/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-starter.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22) - The second step is to set the Cassandre parameter`cassandre.trading.bot.exchange.modes.dry` to `true`: this will make Cassandre simulate the exchange (buying/selling orders, trades) and increase/decrease your account. Now, we need to generate the data you want to use during your JUnit tests. To do so, you can run this on the command line (on Linux) : diff --git a/docs/src/ressources/articles.md b/docs/docs/ressources/articles.md similarity index 76% rename from docs/src/ressources/articles.md rename to docs/docs/ressources/articles.md index c483c4c5f..bad24b1a6 100644 --- a/docs/src/ressources/articles.md +++ b/docs/docs/ressources/articles.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Articles +description: Interesting articles on crypto, trading and bots +--- # Articles ## Trading diff --git a/docs/src/ressources/books.md b/docs/docs/ressources/books.md similarity index 83% rename from docs/src/ressources/books.md rename to docs/docs/ressources/books.md index eaa690d30..99fe750f4 100644 --- a/docs/src/ressources/books.md +++ b/docs/docs/ressources/books.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Books +description: Interesting books on crypto, trading and bots +--- # Books ## Trading diff --git a/docs/src/ressources/how-tos/how-to-build-from-sources.md b/docs/docs/ressources/how-tos/how-to-build-from-sources.md similarity index 69% rename from docs/src/ressources/how-tos/how-to-build-from-sources.md rename to docs/docs/ressources/how-tos/how-to-build-from-sources.md index dfca4f35d..f5295b675 100644 --- a/docs/src/ressources/how-tos/how-to-build-from-sources.md +++ b/docs/docs/ressources/how-tos/how-to-build-from-sources.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Build Cassandre from sources +description: How to build a Cassandre release (and its documentation) on your computer +--- # Build from sources ## Build Cassandre @@ -12,6 +17,11 @@ git clone git@github.com:cassandre-tech/cassandre-trading-bot.git cd cassandre-trading-bot ``` +### Build & install without test +```bash +mvn install -Dgpg.skip -DskipTests +``` + ### Build & install ```bash mvn install -Dgpg.skip diff --git a/docs/src/ressources/how-tos/how-to-create-a-kucoin-account.md b/docs/docs/ressources/how-tos/how-to-create-a-kucoin-account.md similarity index 90% rename from docs/src/ressources/how-tos/how-to-create-a-kucoin-account.md rename to docs/docs/ressources/how-tos/how-to-create-a-kucoin-account.md index 2cbdc9447..ee6dfb470 100644 --- a/docs/src/ressources/how-tos/how-to-create-a-kucoin-account.md +++ b/docs/docs/ressources/how-tos/how-to-create-a-kucoin-account.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Create a Kucoin Account +description: How to create a Kucoin account to use with Cassandre +--- # Create a Kucoin account ## Create a Kucoin account diff --git a/docs/src/ressources/how-tos/how-to-create-a-release.md b/docs/docs/ressources/how-tos/how-to-create-a-release.md similarity index 90% rename from docs/src/ressources/how-tos/how-to-create-a-release.md rename to docs/docs/ressources/how-tos/how-to-create-a-release.md index db4f7bfac..5278371a7 100644 --- a/docs/src/ressources/how-tos/how-to-create-a-release.md +++ b/docs/docs/ressources/how-tos/how-to-create-a-release.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Create a release +description: How to create an official Cassandre release +--- # Create a release ## Prepare the release diff --git a/docs/docs/ressources/how-tos/how-to-fix-common-problems.md b/docs/docs/ressources/how-tos/how-to-fix-common-problems.md new file mode 100644 index 000000000..85ad79e3e --- /dev/null +++ b/docs/docs/ressources/how-tos/how-to-fix-common-problems.md @@ -0,0 +1,39 @@ +--- +lang: en-US +title: Fix common problems +description: How to fix common Cassandre problems +--- +# How to fix common Cassandre problems + +## Your strategies specifies a trading account that doesn't exist +First thing to check: your configuration. If you are connecting to a real exchange (not a sandbox) with your real credentials, you must have those parameters to `false` in your `application.properties`: + +```properties +cassandre.trading.bot.exchange.modes.sandbox=false +cassandre.trading.bot.exchange.modes.dry=false +``` + +Second step, usually, on the exchange, you have one login/password and several accounts, for example: one for trading, one for savings... In order to know if you can buy or can sell, Cassandre needs to know which account on the exchange is the one you are using for trading. + +To do so, you have to implement the [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getTradeAccount%28java.util.Set%29) method in your strategy. This method will be called by Cassandre and gives, as parameter, the list of accounts found on the exchange. + +From that list, you must return one of them. + +To help you, when you start Cassandre, it will display ion the logs the accounts found on the exchange: +``` +2021-11-18 Available accounts on the exchange: +2021-11-18 - Account id / name: trade / trade. +2021-11-18 - 4 TUSD. +2021-11-18 - 5.00007534 UNI. +2021-11-18 - 11.26224436 USDT. +2021-11-18 - 0.01 BTC. +2021-11-18 - Account id / name: main / main. +2021-11-18 - 1 BTC. +``` + +## Way too much request weight used; IP banned until +On Binance, you should not ask for data too often, or you will get a `Way too much request weight used` error, use those parameters in your `application.properties`: +```properties +cassandre.trading.bot.exchange.rates.account=PT30S +cassandre.trading.bot.exchange.rates.ticker=PT30S +cassandre.trading.bot.exchange.rates.trade=PT30S \ No newline at end of file diff --git a/docs/src/ressources/how-tos/how-to-install-development-tools.md b/docs/docs/ressources/how-tos/how-to-install-development-tools.md similarity index 61% rename from docs/src/ressources/how-tos/how-to-install-development-tools.md rename to docs/docs/ressources/how-tos/how-to-install-development-tools.md index dedef56d5..f1e5b80a3 100644 --- a/docs/src/ressources/how-tos/how-to-install-development-tools.md +++ b/docs/docs/ressources/how-tos/how-to-install-development-tools.md @@ -1,12 +1,15 @@ +--- +lang: en-US +title: Install development tools +description: How to use install the development toosl to work on Cassandre and its website +--- # Install development tools ## Tools ```bash -curl -fsSL https://deb.nodesource.com/setup_15.x | sudo -E bash - -curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - -echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list -sudo apt update -sudo apt-get -y install bash curl file libglu1-mesa unzip xz-utils zip nodejs npm yarn +curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - +sudo apt-get install -y nodejs +npm install --global yarn ``` ## [Vuepress](https://vuepress.vuejs.org/) (Documentation) diff --git a/docs/src/ressources/trading-basics.md b/docs/docs/ressources/trading-basics.md similarity index 97% rename from docs/src/ressources/trading-basics.md rename to docs/docs/ressources/trading-basics.md index 402cb73c0..028ddabf9 100644 --- a/docs/src/ressources/trading-basics.md +++ b/docs/docs/ressources/trading-basics.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Trading basics +description: Learn the basics of trading (cryptocurrency, trading, exchange, account, ticker, market order, limit order...) +--- # Trading basics ## What is a cryptocurrency ? diff --git a/docs/src/why-cassandre/features-and-roadmap.md b/docs/docs/why-cassandre/features-and-roadmap.md similarity index 79% rename from docs/src/why-cassandre/features-and-roadmap.md rename to docs/docs/why-cassandre/features-and-roadmap.md index daf7ca3ec..737070d9f 100644 --- a/docs/src/why-cassandre/features-and-roadmap.md +++ b/docs/docs/why-cassandre/features-and-roadmap.md @@ -1,5 +1,11 @@ +--- +lang: en-US +title: Features & roadmap +description: List of Cassandre features (exchange connections, accounts management, orders, trades, and positions) and roadmap +--- # Features & roadmap +## Features * [Create and execute your strategies in minutes](../learn/quickstart.md). * Available as a [Spring boot starter](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22). * Connect to several cryptocurrency exchanges thanks to [XChange](../why-cassandre/supported-cryptocurrency-exchanges.md). @@ -9,4 +15,5 @@ * [Dry mode & backtesting](../learn/dry-mode-and-backtesting.md). * Extensively tested and documented. +## Roadmap Our Roadmap is available on [Github](https://github.com/cassandre-tech/cassandre-trading-bot/milestones?direction=asc&sort=due_date&state=open). \ No newline at end of file diff --git a/docs/src/why-cassandre/overview.md b/docs/docs/why-cassandre/overview.md similarity index 92% rename from docs/src/why-cassandre/overview.md rename to docs/docs/why-cassandre/overview.md index a46d64140..9b0a646ed 100644 --- a/docs/src/why-cassandre/overview.md +++ b/docs/docs/why-cassandre/overview.md @@ -1,27 +1,30 @@ +--- +lang: en-US +title: Overview +description: Cassandre trading bot overview (exchange connections, accounts management, orders, trades, and positions) +--- # Overview -::: tip -If you are new to trading, you can read our tutorial "[Trading basics](../ressources/trading-basics.md)". -::: - ## Introduction A trading bot is a computer program that can automatically place orders to a market or exchange without the need for human intervention. They are working for you 24/7 and never lose their focus. -Cassandre trading bot (available as a [Spring boot starter](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22)) allows you to create and execute your trading strategy in seconds on several crypto exchanges. We also provide a [dry mode and a spring boot starter](../learn/dry-mode-and-backtesting.md) to backtest your strategies on historical and/or real-time data. +Cassandre trading bot (available as a [Spring boot starter](https://search.maven.org/search?q=g:%22tech.cassandre.trading.bot%22%20AND%20a:%22cassandre-trading-bot-spring-boot-starter%22)) allows you to create and execute your trading strategy in seconds on several crypto exchanges. Once the starter is added to your Spring Boot project, it will search for a class having the [@CassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategy.html) annotation and extending [BasicCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicCassandreStrategy.html) or [BasicTa4jCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html). +We also provide a [dry mode and a spring boot starter](../learn/dry-mode-and-backtesting.md) to simulate a virtual exchange so you can backtest your strategies on historical and/or real-time data. + ## BasicCassandreStrategy For a [BasicCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicCassandreStrategy.html), you have to implement : * [getRequestedCurrencyPairs()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getRequestedCurrencyPairs%28%29) to indicate the list of currency pairs tickers you want to receive. -* [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getTradeAccount%28java.util.Set%29) to indicate which account is your trading account. +* [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/CassandreStrategyInterface.html#getTradeAccount%28java.util.Set%29) to indicate which account on the exchange is the one you are using for trading. ## BasicTa4jCassandreStrategy For a [BasicTa4jCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html), you have to implement : * [getRequestedCurrencyPair()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html#getRequestedCurrencyPair%28%29) to indicate the currency pair tickers you want to receive. -* [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#getTradeAccount%28%29) to indicate which account is your trading account. +* [getTradeAccount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#getTradeAccount%28%29) to indicate which account on the exchange is the one you are using for trading. * [getMaximumBarCount()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html#getMaximumBarCount%28%29) to indicate how many bars you want to keep. * [getDelayBetweenTwoBars()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html#getDelayBetweenTwoBars%28%29) to indicate the delay between two bars. * [getStrategy()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html#getStrategy%28%29) to implement your own strategy. @@ -29,14 +32,14 @@ For a [BasicTa4jCassandreStrategy](https://www.javadoc.io/doc/tech.cassandre.tra * [shouldExit()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.html#shouldExit%28%29) to indicate what you want to do when it's time to sell. ## Data updates -To be notified of new data, you can override the following methods : +To receive data from the exchange, you can override the following methods : -* [onAccountsUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onAccountsUpdates(java.util.Map)) to receive updates about your account. +* [onAccountsUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onAccountsUpdates(java.util.Map)) to receive updates about your accounts. * [onTickersUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onTickersUpdates(java.util.Map)) to receive new tickers. * [onOrdersUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onOrdersUpdates(java.util.Map)) to receive updates about your orders. * [onTradesUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onTradesUpdates(java.util.Map)) to receive updates about your trades. * [onPositionsUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onPositionsUpdates(java.util.Map)) to receive updates about your positions. -* [onPositionsStatusUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onPositionsStatusUpdates(java.util.Map)) to receive updates about position status change. +* [onPositionsStatusUpdates()](https://www.javadoc.io/doc/tech.cassandre.trading.bot/cassandre-trading-bot-spring-boot-autoconfigure/latest/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.html#onPositionsStatusUpdates(java.util.Map)) to receive updates about positions status change. ## Buying/selling Inside your strategy, you can create market orders with the methods : diff --git a/docs/src/why-cassandre/supported-cryptocurrency-exchanges.md b/docs/docs/why-cassandre/supported-cryptocurrency-exchanges.md similarity index 83% rename from docs/src/why-cassandre/supported-cryptocurrency-exchanges.md rename to docs/docs/why-cassandre/supported-cryptocurrency-exchanges.md index 8a9b104c3..a21643f52 100644 --- a/docs/src/why-cassandre/supported-cryptocurrency-exchanges.md +++ b/docs/docs/why-cassandre/supported-cryptocurrency-exchanges.md @@ -1,3 +1,8 @@ +--- +lang: en-US +title: Supported cryptocurrency exchanges +description: List of cryptocurrency exchanges supported by Cassandre thanks to XChange library +--- # Supported cryptocurrency exchanges ## Supported by XChange @@ -8,9 +13,10 @@ You can find [here](https://github.com/knowm/XChange/wiki/Exchange-Support) a ta ## Validated by Cassandre Cassandre can theoretically support the 60+ cryptocurrency exchanges the way XChange does but we can't test them all. -Some exchanges provide a sandbox. On those ones, we were able to create integration tests for : +For the exchanges providing a sandbox, we were able to create integration tests for : * [Coinbase](https://github.com/cassandre-tech/cassandre-trading-bot/tree/development/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/integration/coinbasepro): Working except cancel order. * [Gemini](https://github.com/cassandre-tech/cassandre-trading-bot/tree/development/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/integration/gemini): Working but market orders are not supported. * [Kucoin](https://github.com/cassandre-tech/cassandre-trading-bot/tree/development/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/integration/kucoin): Working. -We also run real bots with real assets on [Kucoin](https://www.kucoin.com/ucenter/signup?utm_source=Cassandre), [Coinbase](https://www.coinbase.com/join/straumat) and [Binance](https://accounts.binance.com/en/register?ref=122742137&utm_campaign=web_share_link) to make sure you can use it safely with your real assets. \ No newline at end of file +We also run real bots with real assets on [Kucoin](https://www.kucoin.com/ucenter/signup?utm_source=Cassandre), [Coinbase](https://www.coinbase.com/join/straumat) and [Binance](https://accounts.binance.com/en/register?ref=122742137&utm_campaign=web_share_link) to make sure you can use it safely. + diff --git a/docs/package.json b/docs/package.json old mode 100755 new mode 100644 index 56092a33a..fd063335a --- a/docs/package.json +++ b/docs/package.json @@ -1,22 +1,19 @@ { - "name": "cassandre-trading-bot-documentation", - "version": "0.0.1", - "description": "Cassandre trading bot documentation", + "name": "cassandre-trading-bot-website", + "version": "1.0", "main": "index.js", "authors": { "name": "Stéphane Traumat", "email": "contact@cassandre.tech" }, - "repository": "https://github.com/cassandre-tech/cassandre-trading-bot-documentation/cassandre-trading-bot-documentation", "scripts": { - "dev": "vuepress dev src", - "build": "vuepress build src" + "docs:dev": "vuepress dev docs", + "docs:build": "vuepress build docs" }, "license": "MIT", "devDependencies": { - "@vuepress/plugin-back-to-top": "^1.8.2", - "@vuepress/plugin-google-analytics": "^1.8.2", - "@vuepress/plugin-medium-zoom": "^1.8.2", - "vuepress": "^1.8.2" + "@vuepress/plugin-docsearch": "^2.0.0-beta.27", + "@vuepress/plugin-google-analytics": "^2.0.0-beta.27", + "vuepress": "^2.0.0-beta.27" } } diff --git a/docs/src/.vuepress/components/Foo/Bar.vue b/docs/src/.vuepress/components/Foo/Bar.vue deleted file mode 100755 index 7ee8286a2..000000000 --- a/docs/src/.vuepress/components/Foo/Bar.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/docs/src/.vuepress/components/OtherComponent.vue b/docs/src/.vuepress/components/OtherComponent.vue deleted file mode 100755 index 1d97c7ca8..000000000 --- a/docs/src/.vuepress/components/OtherComponent.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/docs/src/.vuepress/components/demo-component.vue b/docs/src/.vuepress/components/demo-component.vue deleted file mode 100755 index 7d49de79d..000000000 --- a/docs/src/.vuepress/components/demo-component.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/docs/src/.vuepress/enhanceApp.js b/docs/src/.vuepress/enhanceApp.js deleted file mode 100755 index 8452a8689..000000000 --- a/docs/src/.vuepress/enhanceApp.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Client app enhancement file. - * - * https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements - */ - -export default ({ - Vue, // the version of Vue being used in the VuePress app - options, // the options for the root Vue instance - router, // the router instance for the app - siteData // site metadata -}) => { - // ...apply enhancements for the site. -} diff --git a/docs/src/.vuepress/styles/index.styl b/docs/src/.vuepress/styles/index.styl deleted file mode 100755 index 420feb93f..000000000 --- a/docs/src/.vuepress/styles/index.styl +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Custom Styles here. - * - * ref:https://v1.vuepress.vuejs.org/config/#index-styl - */ - -.home .hero img - max-width 450px!important diff --git a/docs/src/.vuepress/styles/palette.styl b/docs/src/.vuepress/styles/palette.styl deleted file mode 100755 index 6490cb359..000000000 --- a/docs/src/.vuepress/styles/palette.styl +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Custom palette here. - * - * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl - */ - -$accentColor = #3eaf7c -$textColor = #2c3e50 -$borderColor = #eaecef -$codeBgColor = #282c34 diff --git a/docs/src/deploy-and-run/qovery.md b/docs/src/deploy-and-run/qovery.md deleted file mode 100644 index 84363eb94..000000000 --- a/docs/src/deploy-and-run/qovery.md +++ /dev/null @@ -1,157 +0,0 @@ -# Deploy & run with Qovery - -## How it works ? -[Qovery](https://www.qovery.com/) is a startup that offers free hosting for your project (free server & a free database) with an amazingly simple way to deploy: you push your code to git and Qovery handles the rest. - -This is how we use it: - * Create a project on github. - * Create an account on Qovery. - * Tell Qovery which repo to use and what kind of database you need. - * Push code to github! - -From now on, everytime you will push your code to github, Qovery will package and deploy it to your server. - -## Create your bot - -### Create & clone the repository -On my github account `straumat`, I created a private project named `qovery-test`. - -The first step is to retrieve the project from Github on your computer: -```bash -git clone git@github.com:straumat/qovery-test.git -``` - -### Create the bot -Create a simple trading bot using one of Cassandre archetypes: -```bash -mvn -B archetype:generate -DarchetypeGroupId=tech.cassandre.trading.bot \ --DarchetypeArtifactId=cassandre-trading-bot-spring-boot-starter-basic-archetype \ --DarchetypeVersion=CASSANDRE_LATEST_RELEASE \ --DgroupId=com.example \ --DartifactId=qovery-test \ --Dversion=1.0-SNAPSHOT \ --Dpackage=com.example -``` - -### Configure the bot - -#### Database connection -Edit `src/main/resources/application.properties` to configure the database:, we will use environment variables that qovery will pass to our application: - -```properties -# Exchange configuration. -cassandre.trading.bot.exchange.driver-class-name=kucoin -cassandre.trading.bot.exchange.username=cassandre.crypto.bot@gmail.com -cassandre.trading.bot.exchange.passphrase=cassandre -cassandre.trading.bot.exchange.key=5df8eea30092f40009cb3c6a -cassandre.trading.bot.exchange.secret=5f6e91e0-796b-4947-b75e-eaa5c06b6bed -# -# Modes. -cassandre.trading.bot.exchange.modes.sandbox=true -cassandre.trading.bot.exchange.modes.dry=true -# -# Exchange API calls rates (ms or standard ISO 8601 duration like 'PT5S'). -cassandre.trading.bot.exchange.rates.account=PT1S -cassandre.trading.bot.exchange.rates.ticker=PT1S -cassandre.trading.bot.exchange.rates.trade=PT1S -# -# Database configuration. -spring.datasource.driver-class-name=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://${QOVERY_DATABASE_QOVERY_TEST_HOST}:5432/${QOVERY_DATABASE_QOVERY_TEST_DATABASE_NAME} -spring.datasource.username=${QOVERY_DATABASE_QOVERY_TEST_USERNAME} -spring.datasource.password=${QOVERY_DATABASE_QOVERY_TEST_PASSWORD} -``` -### Add the PostgreSQL driver -To connect to a PostgreSQL server, you need to add the JDBC driver to your project. Edit your pom.xml and add: -```xml - - - org.postgresql - postgresql - 42.2.17 - - -``` - -### Configure jar final name -To make things more simple to build the Docker image required by qovery, we add this in our pom in the build section: - -```xml - - qovery-test - -``` - -This will ensure that the jar created by the maven process will have the name `qovery-test`. - -### Dockerfile -When pushed to Github, qovery will retrieve your sources and build the Dockerfile at the root of your project. - -This is our Dockerfile, it has two steps: - * First, we use a maven docker image to build our application and creates a spring boot jar. - * Second, we use an openjdk11 image, and we put our jar in it. - -```dockerfile -# Install maven and copy project for compilation. -FROM maven:3.6.3-openjdk-11-slim as build -WORKDIR /build -# Copy just pom.xml (dependencies and dowload them all for offline access later - cache layer). -COPY pom.xml . -RUN mvn dependency:go-offline -B -# Copy source files and compile them (.dockerignore should handle what to copy). -COPY ../.. . -RUN mvn -DskipTests=true package spring-boot:repackage - -# Creates our image. -FROM adoptopenjdk/openjdk11 as runnable -COPY --from=build /build/target/qovery-test.jar app.jar -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"] -``` - -### Push to github -The last step is to commit and push the project to Github: -```bash -cd qovery-test -git add * -git commit -m "first commit" -git branch -M main -git push -u origin main -``` -## Configure Qovery -Connect to [Qovery](https://www.qovery.com/) and signup, then go to the project menu and click on `create a new project`. - -![qovery - Create a project](./images/qovery-create-project.png) - -Enter your project name (`qovery-test`): - -![qovery - Configure the project](./images/qovery-configure-project.png) - -Now, create an application with the name (`qovery-test-app`) and choose `I have an application` on the next screen: - -![qovery - Create an application](./images/qovery-create-application.png) - -Then, select the github project you want to deploy to Qovery: - -![qovery - Select Github project](./images/qovery-select-github-project.png) - -Choose the type of application you have (java): - -![qovery - Select application type](./images/qovery-application-type-choice.png) - -Choose the type of database (PostgreSQL): - -![qovery - Select database type](./images/qovery-database-choice.png) - -Choose the name of the database (`qovery-test-database`): - -![qovery - Configure database](./images/qovery-database-configuration.png) - -Now, check everything is ok the summary page and press create ! - -![qovery - Deployment summary](./images/qovery-deployment-summary.png) - -Qovery will now connect to your repo, creates a configuration file, creates your server and your database, retrieve your sources, build the docker image and run it ! That's it. - -::: tip -Qovery added a configuration file named `.qovery.yml` at the root of your repository. -::: \ No newline at end of file diff --git a/docs/src/index.md b/docs/src/index.md deleted file mode 100755 index d9aebdccf..000000000 --- a/docs/src/index.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -home: true -heroImage: assets/images/logo/cassandre-trading-bot-without-text.png -tagline: Create your java crypto trading bot in minutes -actionText: Quick Start -actionLink: /learn/quickstart -features: -- title: Get into trading with minimum fuss - details: Available as a Spring boot starter, Cassandre takes care of exchange connections, accounts, orders, trades, and positions, so you can focus on building your strategy. -- title: Create your strategy in minutes - details: Just code when you want to create short/long positions, set the rules, and we take care of everything (buying, selling, rules management, orders, trades, and tickers). -- title: Dry mode & backtesting made easy - details: We provide a dry mode to simulate exchange replies to your orders to easily test your strategy. We also provide a spring boot starter to backtest your bot on historical data. -footer: ---- diff --git a/docs/src/learn/database-structure.md b/docs/src/learn/database-structure.md deleted file mode 100644 index 00740ed22..000000000 --- a/docs/src/learn/database-structure.md +++ /dev/null @@ -1,2 +0,0 @@ -# Database structure -![Database structure](./images/cassandre-trading-bot-database.png) diff --git a/docs/src/learn/graphql-api.md b/docs/src/learn/graphql-api.md deleted file mode 100644 index 462d71a1c..000000000 --- a/docs/src/learn/graphql-api.md +++ /dev/null @@ -1,27 +0,0 @@ -# GraphQL API - -## Overview -Cassandre GraphQL API allows you to ONLY query your data (balances, strategies, orders, trades and positions). - -## Installation -To deploy the GraphQLAPI, just add this spring boot starter to your pom: -```xml - - tech.cassandre.trading.bot - cassandre-trading-bot-spring-boot-starter-api-graphql - CASSANDRE_LATEST_RELEASE - -``` - -## Access the API with GraphiQL -Start the application and open a browser to [http://localhost:8080/graphiql](http://localhost:8080/graphiql). GraphiQL is a query editor that comes out of the box with the DGS framework. - -To start, you can try this query to display all your strategies: -``` -query { - strategies{ strategyId name } -} -``` - -## Secure your API -To protect the access to your API with a key, add this property: `cassandre.trading.bot.api.graphql.key` in your `applications.properties`. \ No newline at end of file diff --git a/docs/src/ressources/how-tos/how-to-install-terraform.md b/docs/src/ressources/how-tos/how-to-install-terraform.md deleted file mode 100644 index 0d9a6ca43..000000000 --- a/docs/src/ressources/how-tos/how-to-install-terraform.md +++ /dev/null @@ -1,13 +0,0 @@ -# Install Terraform - -## Install required dependencies -```bash -sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl` -``` - -## Install Terraform -```bash -curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - -sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" -sudo apt-get update && sudo apt-get install terraform -``` diff --git a/pom.xml b/pom.xml index d9d2c53d1..1dd0fd86f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 pom Cassandre trading bot https://github.com/cassandre-tech/cassandre-trading-bot @@ -55,7 +55,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.5 + 2.5.6 @@ -74,10 +74,10 @@ 2.5.5 - Dysprosium-SR24 - 5.0.11 - 6.3.0 - 4.5.0 + Dysprosium-SR25 + 5.0.12 + 6.4.0 + 4.6.1 5.5.2 @@ -90,17 +90,17 @@ 0.14 - 1.4.2 - 4.1.0 + 1.5.0 + 4.1.1 2.6.0 2.12.5 - 4.9.1 + 4.9.7 3.1.2 - 9.0.1 + 9.1 3.2.0 3.8.1 2.22.2 diff --git a/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/pom.xml b/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/pom.xml index 02dc3b956..908a6d7a5 100644 --- a/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/pom.xml +++ b/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/pom.xml @@ -219,7 +219,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../../pom.xml diff --git a/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/src/main/resources/schema/query.graphqls b/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/src/main/resources/schema/query.graphqls index 9100a71c1..4b62b42c5 100644 --- a/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/src/main/resources/schema/query.graphqls +++ b/spring-boot-starter-api/spring-boot-starter-api-graphql/autoconfigure/src/main/resources/schema/query.graphqls @@ -5,41 +5,41 @@ type Query { "Retours all the accounts." accounts: [Account] "Returns the account with the corresponding id." - accountByAccountId(accountId: String): Account + accountByAccountId("Accound id" accountId: String): Account "Returns all the strategies." strategies: [Strategy] "Returns the strategy with the corresponding id." - strategy(id: Int): Strategy + strategy("Strategy id" id: Int): Strategy "Returns the strategy with the corresponding strategyId." - strategyByStrategyId(strategyId: String): Strategy + strategyByStrategyId("Strategy strategyId" strategyId: String): Strategy "Returns all the positions" positions: [Position] "Returns the position with the corresponding id." - position(id: Int): Position + position("Position id" id: Int): Position "Returns all the positions of the specified strategy." - positionsByStrategy(id: Int): [Position] + positionsByStrategy("Position id" id: Int): [Position] "Returns all the positions of the specified strategy." - positionsByStrategyId(strategyId: String): [Position] + positionsByStrategyId("Strategy id" strategyId: String): [Position] "Returns all the positions of the specified strategy and a certain status." - positionsByStrategyAndStatus(id: Int, status: PositionStatus): [Position] + positionsByStrategyAndStatus("Strategy id" id: Int, "Position status" status: PositionStatus): [Position] "Returns all the positions of the specified strategy and a certain status." - positionsByStrategyIdAndStatus(strategyId: String, status: PositionStatus): [Position] + positionsByStrategyIdAndStatus("Strategy strategyId" strategyId: String, "Position status" status: PositionStatus): [Position] "Returns all the orders." orders: [Order] "Returns the order with the corresponding id." - order(id: Int): Order + order("Order id" id: Int): Order "Returns the order with the corresponding orderId." - orderByOrderId(orderId: String): Order + orderByOrderId("Order orderId" orderId: String): Order "Returns all the trades." trades: [Trade] "Returns the trade with the corresponding id." - trade(id: Int): Trade + trade("Trade id" id: Int): Trade "Returns the trade with the corresponding tradeId." - tradeByTradeId(tradeId: String): Trade + tradeByTradeId("Trade tradeId" tradeId: String): Trade } scalar BigDecimal diff --git a/spring-boot-starter-api/spring-boot-starter-api-graphql/starter/pom.xml b/spring-boot-starter-api/spring-boot-starter-api-graphql/starter/pom.xml index 347c6981a..a58a9d4c3 100644 --- a/spring-boot-starter-api/spring-boot-starter-api-graphql/starter/pom.xml +++ b/spring-boot-starter-api/spring-boot-starter-api-graphql/starter/pom.xml @@ -106,7 +106,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../../pom.xml diff --git a/spring-boot-starter-test/autoconfigure/pom.xml b/spring-boot-starter-test/autoconfigure/pom.xml index fe83acb8a..b217491ff 100644 --- a/spring-boot-starter-test/autoconfigure/pom.xml +++ b/spring-boot-starter-test/autoconfigure/pom.xml @@ -222,7 +222,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/spring-boot-starter-test/starter/pom.xml b/spring-boot-starter-test/starter/pom.xml index 678dcc418..f5d33c23a 100644 --- a/spring-boot-starter-test/starter/pom.xml +++ b/spring-boot-starter-test/starter/pom.xml @@ -116,7 +116,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/spring-boot-starter/autoconfigure/pom.xml b/spring-boot-starter/autoconfigure/pom.xml index fef7d9083..ca6526f08 100644 --- a/spring-boot-starter/autoconfigure/pom.xml +++ b/spring-boot-starter/autoconfigure/pom.xml @@ -398,7 +398,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/configuration/StrategiesAutoConfiguration.java b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/configuration/StrategiesAutoConfiguration.java index c925d8221..c8b23bf88 100644 --- a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/configuration/StrategiesAutoConfiguration.java +++ b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/configuration/StrategiesAutoConfiguration.java @@ -178,7 +178,8 @@ public void configure() { if (!strategiesWithoutTradeAccount.isEmpty()) { final String strategyList = String.join(",", strategiesWithoutTradeAccount); throw new ConfigurationException("Your strategies specifies a trading account that doesn't exist", - "Check your getTradeAccount(Set accounts) method as it returns an empty result - Strategies in error : " + strategyList); + "Check your getTradeAccount(Set accounts) method as it returns an empty result - Strategies in error : " + strategyList + "\r\n" + + "See https://trading-bot.cassandre.tech/ressources/how-tos/how-to-fix-common-problems.html#your-strategies-specifies-a-trading-account-that-doesn-t-exist"); } // Check that there is no duplicated strategy ids. diff --git a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.java b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.java index 013a61ee0..aab194df7 100644 --- a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.java +++ b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/BasicTa4jCassandreStrategy.java @@ -38,7 +38,7 @@ public abstract class BasicTa4jCassandreStrategy extends GenericCassandreStrateg private final BarSeries series; /** Ta4j Strategy. */ - private final Strategy strategy; + private Strategy strategy; /** The bar aggregator. */ private final BarAggregator barAggregator = new DurationBarAggregator(getDelayBetweenTwoBars()); @@ -93,6 +93,26 @@ public BasicTa4jCassandreStrategy() { */ public abstract Strategy getStrategy(); + /** + * Returns the executed strategy. + * + * @return strategy + */ + public final Strategy getExecutedStrategy() { + return this.strategy; + } + + /** + * Update the Ta4j strategy used by Cassandre strategy. + * + * @param newStrategy strategy + */ + public void updateStrategy(final Strategy newStrategy) { + if (newStrategy != null) { + strategy = newStrategy; + } + } + @Override public final Set getRequestedCurrencyPairs() { // We only support one currency pair with BasicTa4jCassandreStrategy. @@ -289,6 +309,7 @@ private static class AggregatedBarSubscriber extends BaseSubscriber { /** * Invoke the given function and ask for next bar. + * * @param value the bar value */ @Override diff --git a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.java b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.java index ead6321b5..8083b124d 100644 --- a/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.java +++ b/spring-boot-starter/autoconfigure/src/main/java/tech/cassandre/trading/bot/strategy/GenericCassandreStrategy.java @@ -46,6 +46,7 @@ import java.util.stream.Collectors; import static java.math.BigDecimal.ZERO; +import static java.math.RoundingMode.FLOOR; import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.CLOSED; /** @@ -54,6 +55,9 @@ @SuppressWarnings("checkstyle:DesignForExtension") public abstract class GenericCassandreStrategy implements CassandreStrategyInterface { + /** Big integer scale. */ + private static final int BIGINTEGER_SCALE = 8; + /** Currency mapper. */ protected final CurrencyMapper currencyMapper = Mappers.getMapper(CurrencyMapper.class); @@ -705,6 +709,41 @@ public void onPositionsStatusUpdates(final Map positions) { // ================================================================================================================= // Related to canBuy & canSell methods. + /** + * Returns the amount of a currency I can buy with a certain amount of another currency. + * + * @param amountToUse amount you want to use buy the currency you want + * @param currencyWanted the currency you want to buy + * @return amount of currencyWanted you can buy with amountToUse + */ + public final Optional getEstimatedBuyableAmount(final CurrencyAmountDTO amountToUse, final CurrencyDTO currencyWanted) { + /* + symbol=BTC-USDT + { + "time": 1637270267065, + "sequence": "1622704211505", + "price": "58098.3", + "size": "0.00001747", + "bestBid": "58098.2", + "bestBidSize": "0.038", + "bestAsk": "60000", + "bestAskSize": "0.27476785" + } + This means 1 Bitcoin can be bought with 60000 USDT. + */ + final TickerDTO ticker = lastTickers.get(new CurrencyPairDTO(currencyWanted, amountToUse.getCurrency())); + if (ticker == null) { + // No ticker for this currency pair. + return Optional.empty(); + } else { + // Make the calculation. + // amountToUse: 150 000 USDT. + // CurrencyWanted: BTC. + // How much BTC I can buy ? amountToUse / last + return Optional.of(amountToUse.getValue().divide(ticker.getLast(), BIGINTEGER_SCALE, FLOOR)); + } + } + /** * Returns the cost of buying an amount of a currency pair. * diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/services/dry/TradeServiceTest.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/services/dry/TradeServiceTest.java index 2e5f4162b..d489df984 100644 --- a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/services/dry/TradeServiceTest.java +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/services/dry/TradeServiceTest.java @@ -116,7 +116,9 @@ public void checkCreateBuyAndSellOrder() { assertEquals(orderId02, buyMarketOrder02.getOrder().getOrderId()); // Testing the received order. - with().await().until(() -> strategy.getOrdersUpdatesReceived().stream().anyMatch(o -> o.getOrderId().equals(orderId02))); + with().await().until(() -> strategy.getOrdersUpdatesReceived() + .stream() + .anyMatch(o -> o.getOrderId().equals(orderId02) && o.getStatus().equals(FILLED))); final Optional order02 = strategy.getOrdersUpdatesReceived() .stream() .filter(o -> o.getOrderId().equals(orderId02)) diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/basic/BasicCassandreStrategyTest.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/basic/BasicCassandreStrategyTest.java index c9dd46cbc..7485e8d29 100644 --- a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/basic/BasicCassandreStrategyTest.java +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/basic/BasicCassandreStrategyTest.java @@ -8,6 +8,7 @@ import org.springframework.test.annotation.DirtiesContext; import tech.cassandre.trading.bot.domain.Strategy; import tech.cassandre.trading.bot.dto.user.AccountDTO; +import tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO; import tech.cassandre.trading.bot.repository.StrategyRepository; import tech.cassandre.trading.bot.test.util.junit.BaseTest; import tech.cassandre.trading.bot.test.util.junit.configuration.Configuration; @@ -25,7 +26,9 @@ import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_CLASS; import static tech.cassandre.trading.bot.dto.strategy.StrategyTypeDTO.BASIC_STRATEGY; import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.BTC; +import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.ETH; import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.EUR; +import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.USDT; import static tech.cassandre.trading.bot.test.util.strategies.InvalidStrategy.PARAMETER_INVALID_STRATEGY_ENABLED; import static tech.cassandre.trading.bot.test.util.strategies.NoTradingAccountStrategy.PARAMETER_NO_TRADING_ACCOUNT_STRATEGY_ENABLED; import static tech.cassandre.trading.bot.test.util.strategies.TestableCassandreStrategy.PARAMETER_TESTABLE_STRATEGY_ENABLED; @@ -81,6 +84,14 @@ public void checkStrategyBehavior() { assertTrue(strategy.getEstimatedBuyingCost(ETH_BTC, new BigDecimal(2)).isPresent()); assertEquals(0, new BigDecimal("12").compareTo(strategy.getEstimatedBuyingCost(ETH_BTC, new BigDecimal(2)).get().getValue())); + // Check getEstimatedBuyableAmount() + // 1 ETH = 10000 USDT + final Optional buyableAmount = strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(5000), USDT), ETH); + assertTrue(buyableAmount.isPresent()); + assertEquals(0, new BigDecimal("0.5").compareTo(buyableAmount.get())); + assertFalse(strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(260), EUR), ETH).isPresent()); + assertFalse(strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(260), USDT), EUR).isPresent()); + // Check canBuy() & canSell(). final AccountDTO account = strategy.getAccounts().get("03"); assertNotNull(account); diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/ta4j/BasicTa4jCassandreStrategyTest.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/ta4j/BasicTa4jCassandreStrategyTest.java index 7c71e573b..96ef573f3 100644 --- a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/ta4j/BasicTa4jCassandreStrategyTest.java +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/core/strategy/ta4j/BasicTa4jCassandreStrategyTest.java @@ -8,6 +8,7 @@ import org.springframework.test.annotation.DirtiesContext; import tech.cassandre.trading.bot.domain.Strategy; import tech.cassandre.trading.bot.dto.user.AccountDTO; +import tech.cassandre.trading.bot.dto.util.CurrencyAmountDTO; import tech.cassandre.trading.bot.repository.StrategyRepository; import tech.cassandre.trading.bot.test.util.junit.BaseTest; import tech.cassandre.trading.bot.test.util.junit.configuration.Configuration; @@ -24,6 +25,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_CLASS; import static tech.cassandre.trading.bot.dto.strategy.StrategyTypeDTO.BASIC_TA4J_STRATEGY; +import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.BTC; +import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.ETH; +import static tech.cassandre.trading.bot.dto.util.CurrencyDTO.USDT; import static tech.cassandre.trading.bot.test.util.strategies.InvalidStrategy.PARAMETER_INVALID_STRATEGY_ENABLED; import static tech.cassandre.trading.bot.test.util.strategies.NoTradingAccountStrategy.PARAMETER_NO_TRADING_ACCOUNT_STRATEGY_ENABLED; import static tech.cassandre.trading.bot.test.util.strategies.TestableCassandreStrategy.PARAMETER_TESTABLE_STRATEGY_ENABLED; @@ -73,6 +77,14 @@ public void checkStrategyBehavior() { assertTrue(strategy.getEstimatedBuyingCost(BTC_USDT, new BigDecimal(3)).isPresent()); assertEquals(0, new BigDecimal("390").compareTo(strategy.getEstimatedBuyingCost(BTC_USDT, new BigDecimal(3)).get().getValue())); + // Check getEstimatedBuyableAmount() + // 1 BTC = 130 USDT. + final Optional buyableAmount = strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(260), USDT), BTC); + assertTrue(buyableAmount.isPresent()); + assertEquals(0, new BigDecimal("2").compareTo(buyableAmount.get())); + assertFalse(strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(260), ETH), BTC).isPresent()); + assertFalse(strategy.getEstimatedBuyableAmount(new CurrencyAmountDTO(new BigDecimal(260), USDT), ETH).isPresent()); + // Test for simplified canBuy() & canSell(). // 1 BTC / 150 in my account. // 1 BTC = 390 UST. diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/Isue794Test.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/Isue794Test.java new file mode 100644 index 000000000..26a5b9688 --- /dev/null +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/Isue794Test.java @@ -0,0 +1,57 @@ +package tech.cassandre.trading.bot.test.issues.v5_x.v5_0_6; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.ta4j.core.BaseBarSeriesBuilder; +import org.ta4j.core.BaseStrategy; +import org.ta4j.core.indicators.SMAIndicator; +import org.ta4j.core.indicators.helpers.ClosePriceIndicator; +import org.ta4j.core.rules.OverIndicatorRule; +import org.ta4j.core.rules.UnderIndicatorRule; +import tech.cassandre.trading.bot.test.util.junit.BaseTest; +import tech.cassandre.trading.bot.test.util.junit.configuration.Configuration; +import tech.cassandre.trading.bot.test.util.junit.configuration.Property; +import tech.cassandre.trading.bot.test.util.strategies.TestableTa4jCassandreStrategy; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD; +import static tech.cassandre.trading.bot.test.util.junit.configuration.ConfigurationExtension.PARAMETER_EXCHANGE_DRY; +import static tech.cassandre.trading.bot.test.util.strategies.InvalidStrategy.PARAMETER_INVALID_STRATEGY_ENABLED; +import static tech.cassandre.trading.bot.test.util.strategies.NoTradingAccountStrategy.PARAMETER_NO_TRADING_ACCOUNT_STRATEGY_ENABLED; +import static tech.cassandre.trading.bot.test.util.strategies.TestableCassandreStrategy.PARAMETER_TESTABLE_STRATEGY_ENABLED; +import static tech.cassandre.trading.bot.test.util.strategies.TestableTa4jCassandreStrategy.PARAMETER_TESTABLE_TA4J_STRATEGY_ENABLED; + +@SpringBootTest +@DisplayName("Github issue 794") +@Configuration({ + @Property(key = PARAMETER_EXCHANGE_DRY, value = "true"), + @Property(key = PARAMETER_INVALID_STRATEGY_ENABLED, value = "false"), + @Property(key = PARAMETER_TESTABLE_STRATEGY_ENABLED, value = "false"), + @Property(key = PARAMETER_TESTABLE_TA4J_STRATEGY_ENABLED, value = "true"), + @Property(key = PARAMETER_NO_TRADING_ACCOUNT_STRATEGY_ENABLED, value = "false") +}) +@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD) +public class Isue794Test extends BaseTest { + + @Autowired + private TestableTa4jCassandreStrategy strategy; + + @Test + @DisplayName("Update the Strategy on a BasicTa4jCassandreStrategy") + public void updateTa4jStrategyInBasicTa4jCassandreStrategy() { + assertEquals("Initial strategy", strategy.getExecutedStrategy().getName()); + + // Creating a new strategy. + ClosePriceIndicator closePrice = new ClosePriceIndicator(new BaseBarSeriesBuilder().build()); + SMAIndicator sma = new SMAIndicator(closePrice, 3); + final BaseStrategy newStrategy = new BaseStrategy("New strategy", new UnderIndicatorRule(sma, closePrice), new OverIndicatorRule(sma, closePrice)); + + // Updating the strategy and checking the change. + strategy.updateStrategy(newStrategy); + assertEquals("New strategy", strategy.getExecutedStrategy().getName()); + } + +} diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/package-info.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/package-info.java new file mode 100644 index 000000000..129f59d6c --- /dev/null +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/issues/v5_x/v5_0_6/package-info.java @@ -0,0 +1,4 @@ +/** + * GitHub issues for 5.0.6. + */ +package tech.cassandre.trading.bot.test.issues.v5_x.v5_0_6; \ No newline at end of file diff --git a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/util/strategies/TestableTa4jCassandreStrategy.java b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/util/strategies/TestableTa4jCassandreStrategy.java index ae2ff3254..2cb0b9c9e 100644 --- a/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/util/strategies/TestableTa4jCassandreStrategy.java +++ b/spring-boot-starter/autoconfigure/src/test/java/tech/cassandre/trading/bot/test/util/strategies/TestableTa4jCassandreStrategy.java @@ -84,7 +84,7 @@ public Duration getDelayBetweenTwoBars() { public Strategy getStrategy() { ClosePriceIndicator closePrice = new ClosePriceIndicator(getSeries()); SMAIndicator sma = new SMAIndicator(closePrice, 3); - return new BaseStrategy(new UnderIndicatorRule(sma, closePrice), new OverIndicatorRule(sma, closePrice)); + return new BaseStrategy("Initial strategy", new UnderIndicatorRule(sma, closePrice), new OverIndicatorRule(sma, closePrice)); } @Override diff --git a/spring-boot-starter/starter/pom.xml b/spring-boot-starter/starter/pom.xml index 58cd642e3..6a87b87bb 100644 --- a/spring-boot-starter/starter/pom.xml +++ b/spring-boot-starter/starter/pom.xml @@ -112,7 +112,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/trading-bot-archetypes/basic-archetype/pom.xml b/trading-bot-archetypes/basic-archetype/pom.xml index 65591be8c..1ab22c0e1 100644 --- a/trading-bot-archetypes/basic-archetype/pom.xml +++ b/trading-bot-archetypes/basic-archetype/pom.xml @@ -104,7 +104,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/pom.xml b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/pom.xml index acdc915c3..cb526debe 100644 --- a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/pom.xml +++ b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/pom.xml @@ -114,4 +114,18 @@ + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + diff --git a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/main/java/SimpleStrategy.java b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/main/java/SimpleStrategy.java index c3ebff92c..e42610050 100644 --- a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/main/java/SimpleStrategy.java +++ b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/main/java/SimpleStrategy.java @@ -29,7 +29,7 @@ public final class SimpleStrategy extends BasicCassandreStrategy { @Override public Set getRequestedCurrencyPairs() { - // We only ask about ETC/BTC (Base currency : BTC / Quote currency : USDT). + // We only ask BTC/USDT tickers (Base currency : BTC / Quote currency : USDT). return Set.of(new CurrencyPairDTO(BTC, USDT)); } @@ -37,10 +37,12 @@ public Set getRequestedCurrencyPairs() { public Optional getTradeAccount(Set accounts) { // From all the accounts we have on the exchange, we must return the one we use for trading. if (accounts.size() == 1) { - return accounts.stream().findAny(); + // If there is only one on the exchange, we choose this one. + return accounts.stream().findFirst(); } else { + // If there are several accounts on the exchange, we choose the one with the name "trade". return accounts.stream() - .filter(a -> "trade".equals(a.getName())) + .filter(a -> "trade".equalsIgnoreCase(a.getName())) .findFirst(); } } diff --git a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/test/java/SimpleStrategyTest.java b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/test/java/SimpleStrategyTest.java index 831041988..c1020d767 100644 --- a/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/test/java/SimpleStrategyTest.java +++ b/trading-bot-archetypes/basic-archetype/src/main/resources/archetype-resources/src/test/java/SimpleStrategyTest.java @@ -39,7 +39,7 @@ public class SimpleStrategyTest { public void receivedData() { await().forever().until(() -> tickerFluxMock.isFluxDone()); - // Waiting to see if the strategy received the accounts update (we have two accounts). + // Waiting to see if the strategy received the accounts update. await().untilAsserted(() -> assertEquals(strategy.getAccounts().size(), 2)); } diff --git a/trading-bot-archetypes/basic-ta4j-archetype/pom.xml b/trading-bot-archetypes/basic-ta4j-archetype/pom.xml index 4f38462e3..8bd7d2352 100644 --- a/trading-bot-archetypes/basic-ta4j-archetype/pom.xml +++ b/trading-bot-archetypes/basic-ta4j-archetype/pom.xml @@ -104,7 +104,7 @@ tech.cassandre.trading.bot cassandre-trading-bot-project - 5.0.5 + 5.0.6 ../../pom.xml diff --git a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/pom.xml b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/pom.xml index acdc915c3..cb526debe 100644 --- a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/pom.xml +++ b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/pom.xml @@ -114,4 +114,18 @@ + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + diff --git a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/SimpleTa4jStrategy.java b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/SimpleTa4jStrategy.java index eb7e3b112..6d330116d 100644 --- a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/SimpleTa4jStrategy.java +++ b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/SimpleTa4jStrategy.java @@ -36,7 +36,7 @@ public final class SimpleTa4jStrategy extends BasicTa4jCassandreStrategy { @Override public CurrencyPairDTO getRequestedCurrencyPair() { - // We only ask about ETC/BTC (Base currency : BTC / Quote currency : USDT). + // We only ask BTC/USDT tickers (Base currency : BTC / Quote currency : USDT). return new CurrencyPairDTO(BTC, USDT); } @@ -44,10 +44,12 @@ public CurrencyPairDTO getRequestedCurrencyPair() { public Optional getTradeAccount(Set accounts) { // From all the accounts we have on the exchange, we must return the one we use for trading. if (accounts.size() == 1) { - return accounts.stream().findAny(); + // If there is only one on the exchange, we choose this one. + return accounts.stream().findFirst(); } else { + // If there are several accounts on the exchange, we choose the one with the name "trade". return accounts.stream() - .filter(a -> "trade".equals(a.getName())) + .filter(a -> "trade".equalsIgnoreCase(a.getName())) .findFirst(); } } diff --git a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/package-info.java b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/package-info.java index d96980c96..a8f3dc749 100644 --- a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/package-info.java +++ b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/main/java/package-info.java @@ -2,6 +2,6 @@ #set( $symbol_dollar = '$' ) #set( $symbol_escape = '\' ) /** - * Simple strategy. + * Simple Ta4j strategy. */ package ${package}; \ No newline at end of file diff --git a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/test/java/SimpleTa4jStrategyTest.java b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/test/java/SimpleTa4jStrategyTest.java index 3f2118880..c0290a0f7 100644 --- a/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/test/java/SimpleTa4jStrategyTest.java +++ b/trading-bot-archetypes/basic-ta4j-archetype/src/main/resources/archetype-resources/src/test/java/SimpleTa4jStrategyTest.java @@ -20,11 +20,11 @@ import static tech.cassandre.trading.bot.dto.position.PositionStatusDTO.CLOSED; /** - * Basic Ta4j strategy test. + * Simple Ta4J strategy test. */ @SpringBootTest @Import(TickerFluxMock.class) -@DisplayName("Simple ta4j strategy test") +@DisplayName("Simple Ta4J strategy test") public class SimpleTa4jStrategyTest { @Autowired