freqtrade UI edits

This revision is from 2024/06/09 20:14. You can Restore it.

To present frequi to the public, all the problem API calls need to be deleted and the username and password of the bots need to be added to auth_rpc.py so that they are not displayed to the public. Furtheron consider running it in sandbox, or container.

Location of essential edits, these are the API endpoints.:

/home/x/freqtrade/freqtrade/rpc/rpc.py

/home/x/freqtrade/freqtrade/rpc/api_server/

/home/x/freqtrade/freqtrade/rpc/api_server/api_v1.py

/home/x/freqtrade/freqtrade/rpc/api_server/ui

/home/x/freqtrade/.venv/lib/python3.x/site-packages/freqtrade/rpc/api_server/ui

Essentially, it is a matter of making the UI readonly, delete all the functions that control the bot in the python file above and then test their execution in frequi source code...

git clone https://github.com/freqtrade/frequi.git

cd frequi

pnpm install

pnpm run dev

To add your bots programmically, edit vue.app...

<template>

<div id="app" class="d-flex flex-column dvh-100" :style="colorStore.cssVars">

<NavBar />

<BaseAlert></BaseAlert>

<BodyLayout class="flex-fill overflow-auto" />

<NavFooter />

</div>

</template>

<script setup lang="ts">

import { onMounted, beforeMount, watch } from 'vue';

import { setTimezone } from './shared/formatters';

import { useBotStore } from './stores/ftbotwrapper';

import { useUserService } from './shared/userService';

import { useSettingsStore } from './stores/settings';

import { useColorStore } from './stores/colors';

import { AuthPayload } from '@/types';

const settingsStore = useSettingsStore();

const colorStore = useColorStore();

const botStore = useBotStore();

onMounted(async () => {

setTimezone(settingsStore.timezone);

colorStore.updateProfitLossColor();

localStorage.removeItem('ftAuthLoginInfo');

localStorage.removeItem('ftSelectedBot');

const addBot = async (botName: string, apiUrl: string, username: string, password: string) => {

const auth: AuthPayload = {

botName,

url: apiUrl,

username,

password,

};

// Check if the bot already exists

const existingBot = Object.values(botStore.availableBots).find(

(bot) => bot.botName === botName && bot.botUrl === apiUrl

);

if (!existingBot) {

try {

const userService = useUserService(botStore.nextBotId);

await userService.login(auth);

const newBotId = botStore.nextBotId;

botStore.addBot({

botName,

botId: newBotId,

botUrl: apiUrl,

sortId: Object.keys(botStore.availableBots).length + 1,

});

botStore.selectBot(newBotId);

botStore.allRefreshFull();

console.log('Bot added successfully:', botName);

} catch (error) {

console.error('Failed to add bot:', botName, error);

}

} else {

console.log('Bot already exists:', botName);

}

};

await addBot('My New Bot', 'http://127.0.0.1:4000', 'freqtrader', 'xxxxxxx');

await addBot('Another Bot', 'http://127.0.0.1:8081', 'freqtrader', 'xxxxxxxx');

await addBot('Another Bot 2', 'http://127.0.0.1:8082', 'freqtrader', 'xxxxxxxx');

});

watch(

() => settingsStore.timezone,

(tz) => {

console.log('timezone changed', tz);

setTimezone(tz);

},

);

</script>

<style scoped>

#app {

font-family: Avenir, Helvetica, Arial, sans-serif;

-webkit-font-smoothing: antialiased;

-moz-osx-font-smoothing: grayscale;

text-align: center;

}

/* * {

outline: 1px solid #f00!important;

} */

</style>

Delete these...

start Starts the trader.

stop Stops the trader.

stopbuy Stops the trader from opening new trades. Gracefully closes open trades according to their rules.

reload_config Reloads the configuration file.

delete_trade <trade_id> Remove trade from the database. Tries to close open orders. Requires manual handling of this trade on the exchange.

show_config Shows part of the current configuration with relevant settings to operation.

logs Shows last log messages.

forcesell <trade_id> Instantly sells the given trade (Ignoring minimum_roi).

forcesell all Instantly sells all open trades (Ignoring minimum_roi).

forcebuy <pair> [rate] Instantly buys the given pair. Rate is optional. (forcebuy_enable must be set to True)

strategies List strategies in strategy directory. Alpha

strategy <strategy> Get specific Strategy content. Alpha

Keep these...

ping Simple command testing the API Readiness - requires no authentication.

trades List last trades.

status Lists all open trades.

count Displays number of trades used and available.

locks Displays currently locked pairs.

profit Display a summary of your profit/loss from close trades and some stats about your performance.

performance Show performance of each finished trade grouped by pair.

balance Show account balance per currency.

daily <n> Shows profit or loss per day, over the last n days (n defaults to 7).

stats Display a summary of profit / loss reasons as well as average holding times.

whitelist Show the current whitelist.

blacklist [pair] Show the current blacklist, or adds a pair to the blacklist.

edge Show validated pairs by Edge if it is enabled.

pair_candles Returns dataframe for a pair / timeframe combination while the bot is running. Alpha

pair_history Returns an analyzed dataframe for a given timerange, analyzed by a given strategy. Alpha

plot_config Get plot config from the strategy (or nothing if not configured). Alpha

available_pairs List available backtest data. Alpha

version Show version.

Files in question...

grep -irln "@router."

freqtrade/rpc/api_server/api_v1.py

freqtrade/rpc/api_server/api_auth.py

freqtrade/rpc/api_server/web_ui.py

freqtrade/rpc/api_server/api_ws.py

freqtrade/rpc/api_server/api_backtest.py

freqtrade/rpc/api_server/api_background_tasks.py

.venv/lib/python3.10/site-packages/fastapi/routing.py

.venv/lib/python3.10/site-packages/fastapi/__pycache__/routing.cpython-310.pyc

grep -ir "@router."

freqtrade/rpc/api_server/api_v1.py:@router_public.get("/ping", response_model=Ping)

freqtrade/rpc/api_server/api_v1.py:@router.get("/version", response_model=Version, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/balance", response_model=Balances, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/count", response_model=Count, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/entries", response_model=List[Entry], tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/exits", response_model=List[Exit], tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/mix_tags", response_model=List[MixTag], tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/performance", response_model=List[PerformanceEntry], tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/profit", response_model=Profit, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/stats", response_model=Stats, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/daily", response_model=DailyWeeklyMonthly, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/weekly", response_model=DailyWeeklyMonthly, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/monthly", response_model=DailyWeeklyMonthly, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/status", response_model=List[OpenTradeSchema], tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/trades", tags=["info", "trading"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/trade/{tradeid}", response_model=OpenTradeSchema, tags=["info", "trading"])

freqtrade/rpc/api_server/api_v1.py:@router.delete("/trades/{tradeid}", response_model=DeleteTrade, tags=["info", "trading"])

freqtrade/rpc/api_server/api_v1.py:@router.delete("/trades/{tradeid}/open-order", response_model=OpenTradeSchema, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/trades/{tradeid}/reload", response_model=OpenTradeSchema, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/edge", tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/show_config", response_model=ShowConfig, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/forceenter", response_model=ForceEnterResponse, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/forcebuy", response_model=ForceEnterResponse, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/forceexit", response_model=ResultMsg, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/forcesell", response_model=ResultMsg, tags=["trading"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/blacklist", response_model=BlacklistResponse, tags=["info", "pairlist"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/blacklist", response_model=BlacklistResponse, tags=["info", "pairlist"])

freqtrade/rpc/api_server/api_v1.py:@router.delete("/blacklist", response_model=BlacklistResponse, tags=["info", "pairlist"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/whitelist", response_model=WhitelistResponse, tags=["info", "pairlist"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/locks", response_model=Locks, tags=["info", "locks"])

freqtrade/rpc/api_server/api_v1.py:@router.delete("/locks/{lockid}", response_model=Locks, tags=["info", "locks"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/locks/delete", response_model=Locks, tags=["info", "locks"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/locks", response_model=Locks, tags=["info", "locks"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/logs", response_model=Logs, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/start", response_model=StatusMsg, tags=["botcontrol"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/stop", response_model=StatusMsg, tags=["botcontrol"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/stopentry", response_model=StatusMsg, tags=["botcontrol"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/stopbuy", response_model=StatusMsg, tags=["botcontrol"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/reload_config", response_model=StatusMsg, tags=["botcontrol"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/pair_candles", response_model=PairHistory, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/pair_candles", response_model=PairHistory, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/pair_history", response_model=PairHistory, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.post("/pair_history", response_model=PairHistory, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/plot_config", response_model=PlotConfig, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/strategies", response_model=StrategyListResponse, tags=["strategy"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/strategy/{strategy}", response_model=StrategyResponse, tags=["strategy"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/exchanges", response_model=ExchangeListResponse, tags=[])

freqtrade/rpc/api_server/api_v1.py:@router.get("/freqaimodels", response_model=FreqAIModelListResponse, tags=["freqai"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/available_pairs", response_model=AvailablePairs, tags=["candle data"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/sysinfo", response_model=SysInfo, tags=["info"])

freqtrade/rpc/api_server/api_v1.py:@router.get("/health", response_model=Health, tags=["info"])

freqtrade/rpc/api_server/api_auth.py:@router_login.post("/token/login", response_model=AccessAndRefreshToken)

freqtrade/rpc/api_server/api_auth.py:@router_login.post("/token/refresh", response_model=AccessToken)

freqtrade/rpc/api_server/web_ui.py:@router_ui.get("/favicon.ico", include_in_schema=False)

freqtrade/rpc/api_server/web_ui.py:@router_ui.get("/fallback_file.html", include_in_schema=False)

freqtrade/rpc/api_server/web_ui.py:@router_ui.get("/ui_version", include_in_schema=False)

freqtrade/rpc/api_server/web_ui.py:@router_ui.get("/{rest_of_path:path}", include_in_schema=False)

freqtrade/rpc/api_server/api_ws.py:@router.websocket("/message/ws")

freqtrade/rpc/api_server/api_backtest.py:@router.post("/backtest", response_model=BacktestResponse, tags=["webserver", "backtest"])

freqtrade/rpc/api_server/api_backtest.py:@router.get("/backtest", response_model=BacktestResponse, tags=["webserver", "backtest"])

freqtrade/rpc/api_server/api_backtest.py:@router.delete("/backtest", response_model=BacktestResponse, tags=["webserver", "backtest"])

freqtrade/rpc/api_server/api_backtest.py:@router.get("/backtest/abort", response_model=BacktestResponse, tags=["webserver", "backtest"])

freqtrade/rpc/api_server/api_backtest.py:@router.get(

freqtrade/rpc/api_server/api_backtest.py:@router.get(

freqtrade/rpc/api_server/api_backtest.py:@router.delete(

freqtrade/rpc/api_server/api_backtest.py:@router.patch(

freqtrade/rpc/api_server/api_backtest.py:@router.get(

freqtrade/rpc/api_server/api_background_tasks.py:@router.get("/background", response_model=List[BackgroundTaskStatus], tags=["webserver"])

freqtrade/rpc/api_server/api_background_tasks.py:@router.get("/background/{jobid}", response_model=BackgroundTaskStatus, tags=["webserver"])

freqtrade/rpc/api_server/api_background_tasks.py:@router.get(

freqtrade/rpc/api_server/api_background_tasks.py:@router.post("/pairlists/evaluate", response_model=BgJobStarted, tags=["pairlists", "webserver"])

freqtrade/rpc/api_server/api_background_tasks.py:@router.get(

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.get("/users/", tags=["users"])

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.websocket("/ws")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.get("/items/")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.put("/items/{item_id}")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.post("/items/")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.delete("/items/{item_id}")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.options("/items/")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.head("/items/", status_code=204)

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.patch("/items/")

.venv/lib/python3.10/site-packages/fastapi/routing.py: @router.trace("/items/{item_id}")

To autologin:

hardcode username and password that matches the bot in the file api_auth.py

regardless of the username and password entered in the frequi, the login will be successful.

To autoadd the bot in frequi, edit the source and programmically add,

// Strategy 1

const botId1 = 'ftbot.1';

const auth1 = new Un(botId1);

const loginData1 = {

botName: 'Strategy1',

url: 'http://127.0.0.1:8080',

username: 'freqtrader',

password: 'password'

};

auth1.login(loginData1)

.then(() => {

console.log('Login successful for Strategy1');

// Ensure tokens are stored

console.log('Access Token:', auth1.getAccessToken());

console.log('Refresh Token:', auth1.getRefreshToken());

console.log('Set Token:', auth1.setAccessToken());

// Continue with further operations after login

})

.catch((error) => {

console.error('Login failed for Strategy1:', error);

// Handle login error for Strategy1

});

repeat for each bot.

  

📝 📜 ⏱️ ⬆️