Synth api (#28)
* Add synthApi * Put confidence for Synth proba * Update the code * Update readme * Fix bootstraping * fix github build * Update the endpoints for scenario * Add scenario and update backtest modal * Update bot modal * Update interfaces for synth * add synth to backtest * Add Kelly criterion and better signal * Update signal confidence * update doc * save leaderboard and prediction * Update nswag to generate ApiClient in the correct path * Unify the trading modal * Save miner and prediction * Update messaging and block new signal until position not close when flipping off * Rename strategies to indicators * Update doc * Update chart + add signal name * Fix signal direction * Update docker webui * remove crypto npm * Clean * Fix mobile a bit
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { create } from 'zustand'
|
import {create} from 'zustand'
|
||||||
|
|
||||||
import type { MoneyManagement } from '../../generated/ManagingApi'
|
import type {MoneyManagement} from '../../generated/ManagingApi'
|
||||||
|
|
||||||
type CustomMoneyManagementStore = {
|
type CustomMoneyManagementStore = {
|
||||||
setCustomMoneyManagement: (custom: MoneyManagement) => void
|
setCustomMoneyManagement: (custom: MoneyManagement | null) => void
|
||||||
moneyManagement: MoneyManagement | null
|
moneyManagement: MoneyManagement | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {create} from 'zustand'
|
|||||||
import type {Scenario} from '../../generated/ManagingApi'
|
import type {Scenario} from '../../generated/ManagingApi'
|
||||||
|
|
||||||
type CustomScenarioStore = {
|
type CustomScenarioStore = {
|
||||||
setCustomScenario: (custom: Scenario) => void
|
setCustomScenario: (custom: Scenario | null) => void
|
||||||
scenario: Scenario | null
|
scenario: Scenario | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import type {IModalProps} from '../../../global/type'
|
import type {IModalProps} from '../../../global/type.tsx'
|
||||||
|
|
||||||
import ModalHeader from './ModalHeader'
|
import ModalHeader from './ModalHeader'
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import type { IModalProps } from '../../../global/type'
|
import type {IModalProps} from '../../../global/type.tsx'
|
||||||
|
|
||||||
const ModalHeader: React.FC<IModalProps> = ({ onClose, titleHeader }: any) => {
|
const ModalHeader: React.FC<IModalProps> = ({ onClose, titleHeader }: any) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ import type {
|
|||||||
MoneyManagement,
|
MoneyManagement,
|
||||||
RunBacktestRequest,
|
RunBacktestRequest,
|
||||||
StartBotRequest,
|
StartBotRequest,
|
||||||
TradingBotConfig
|
TradingBotConfig,
|
||||||
|
TradingBotConfigRequest
|
||||||
} from '../../../generated/ManagingApi'
|
} from '../../../generated/ManagingApi'
|
||||||
import {BacktestClient, BotClient, MoneyManagementClient} from '../../../generated/ManagingApi'
|
import {BacktestClient, BotClient, MoneyManagementClient} from '../../../generated/ManagingApi'
|
||||||
import type {IBacktestCards} from '../../../global/type'
|
import type {IBacktestCards} from '../../../global/type.tsx'
|
||||||
import MoneyManagementModal from '../../../pages/settingsPage/moneymanagement/moneyManagementModal'
|
import MoneyManagementModal from '../../../pages/settingsPage/moneymanagement/moneyManagementModal'
|
||||||
import {CardPosition, CardText, Toast} from '../../mollecules'
|
import {CardPosition, CardText, Toast} from '../../mollecules'
|
||||||
import CardPositionItem from '../Trading/CardPositionItem'
|
import CardPositionItem from '../Trading/CardPositionItem'
|
||||||
@@ -119,9 +120,7 @@ const BacktestCards: React.FC<IBacktestCards> = ({ list, setBacktests }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const request: StartBotRequest = {
|
const request: StartBotRequest = {
|
||||||
config: tradingBotConfig,
|
config: tradingBotConfig as unknown as TradingBotConfigRequest,
|
||||||
// Only use the money management name if it's not a custom money management
|
|
||||||
moneyManagementName: isCustomMoneyManagement ? undefined : moneyManagementName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await client
|
await client
|
||||||
@@ -165,21 +164,19 @@ const BacktestCards: React.FC<IBacktestCards> = ({ list, setBacktests }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const request: RunBacktestRequest = {
|
const request: RunBacktestRequest = {
|
||||||
config: optimizedConfig,
|
config: optimizedConfig as unknown as TradingBotConfigRequest,
|
||||||
startDate: startDate,
|
startDate: startDate,
|
||||||
endDate: endDate,
|
endDate: endDate,
|
||||||
balance: backtest.walletBalances[0].value,
|
balance: backtest.walletBalances[0].value,
|
||||||
watchOnly: false,
|
watchOnly: false,
|
||||||
save: false,
|
save: false,
|
||||||
moneyManagementName: undefined, // We're passing the moneyManagement object directly
|
|
||||||
moneyManagement: optimizedConfig.moneyManagement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await client
|
await client
|
||||||
.backtest_Run(request)
|
.backtest_Run(request)
|
||||||
.then((backtest: Backtest) => {
|
.then((backtest: Backtest) => {
|
||||||
t.update('success', `${backtest.config.ticker} Backtest Succeeded`)
|
t.update('success', `${backtest.config.ticker} Backtest Succeeded`)
|
||||||
setBacktests((arr) => [...arr, backtest])
|
setBacktests((arr: Backtest[]) => [...arr, backtest])
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
t.update('error', 'Error :' + err)
|
t.update('error', 'Error :' + err)
|
||||||
@@ -193,7 +190,7 @@ const BacktestCards: React.FC<IBacktestCards> = ({ list, setBacktests }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-wrap m-4 -mx-4">
|
<div className="flex flex-wrap m-4 -mx-4">
|
||||||
{list?.map((backtest: Backtest, index) => (
|
{list?.map((backtest: Backtest, index: number) => (
|
||||||
<div
|
<div
|
||||||
key={index.toString()}
|
key={index.toString()}
|
||||||
className="sm:w-1/2 md:w-1/2 xl:w-1/2 w-full p-2"
|
className="sm:w-1/2 md:w-1/2 xl:w-1/2 w-full p-2"
|
||||||
@@ -213,7 +210,7 @@ const BacktestCards: React.FC<IBacktestCards> = ({ list, setBacktests }) => {
|
|||||||
positions={backtest.positions}
|
positions={backtest.positions}
|
||||||
walletBalances={backtest.walletBalances}
|
walletBalances={backtest.walletBalances}
|
||||||
signals={backtest.signals}
|
signals={backtest.signals}
|
||||||
strategiesValues={backtest.strategiesValues}
|
indicatorsValues={backtest.indicatorsValues}
|
||||||
width={720}
|
width={720}
|
||||||
height={512}
|
height={512}
|
||||||
></TradeChart>
|
></TradeChart>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, {useEffect, useState} from 'react'
|
import React, {useEffect, useState} from 'react'
|
||||||
|
|
||||||
import type {Backtest, MoneyManagement} from '../../../generated/ManagingApi'
|
import type {Backtest, MoneyManagement} from '../../../generated/ManagingApi'
|
||||||
import type {IModalProps} from '../../../global/type'
|
|
||||||
import {Modal} from '../../mollecules'
|
import {Modal} from '../../mollecules'
|
||||||
|
import type {IModalProps} from '../../../global/type.tsx'
|
||||||
|
|
||||||
interface IBotNameModalProps extends IModalProps {
|
interface IBotNameModalProps extends IModalProps {
|
||||||
backtest: Backtest
|
backtest: Backtest
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ const CustomScenario: React.FC<ICustomScenario> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Dynamic parameter inputs based on indicator type */}
|
{/* Dynamic parameter inputs based on indicator type */}
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
{getRequiredParams(indicator.type || indicatorTypes[0].type).map((param) => (
|
{getRequiredParams(indicator.type || indicatorTypes[0].type).map((param) => (
|
||||||
<FormInput key={param} label={param.charAt(0).toUpperCase() + param.slice(1)} htmlFor={`${param}-${index}`} inline={false}>
|
<FormInput key={param} label={param.charAt(0).toUpperCase() + param.slice(1)} htmlFor={`${param}-${index}`} inline={false}>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import React, {useEffect, useState} from 'react'
|
|||||||
import {type SubmitHandler, useForm} from 'react-hook-form'
|
import {type SubmitHandler, useForm} from 'react-hook-form'
|
||||||
|
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
|
import {useCustomMoneyManagement} from '../../../app/store/customMoneyManagement'
|
||||||
|
import {useCustomScenario} from '../../../app/store/customScenario'
|
||||||
import {
|
import {
|
||||||
AccountClient,
|
AccountClient,
|
||||||
BacktestClient,
|
BacktestClient,
|
||||||
@@ -136,6 +138,8 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
const [selectedTicker, setSelectedTicker] = useState<Ticker | undefined>(undefined);
|
const [selectedTicker, setSelectedTicker] = useState<Ticker | undefined>(undefined);
|
||||||
|
|
||||||
const { apiUrl } = useApiUrlStore();
|
const { apiUrl } = useApiUrlStore();
|
||||||
|
const { setCustomMoneyManagement: setGlobalCustomMoneyManagement } = useCustomMoneyManagement();
|
||||||
|
const { setCustomScenario: setGlobalCustomScenario } = useCustomScenario();
|
||||||
|
|
||||||
// API clients
|
// API clients
|
||||||
const scenarioClient = new ScenarioClient({}, apiUrl);
|
const scenarioClient = new ScenarioClient({}, apiUrl);
|
||||||
@@ -185,6 +189,18 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
setSelectedTicker(backtest.config.ticker);
|
setSelectedTicker(backtest.config.ticker);
|
||||||
}
|
}
|
||||||
setValue('scenarioName', backtest.config.scenarioName || '');
|
setValue('scenarioName', backtest.config.scenarioName || '');
|
||||||
|
|
||||||
|
// Handle custom scenario from backtest
|
||||||
|
if ((backtest.config as any).scenario) {
|
||||||
|
setShowCustomScenario(true);
|
||||||
|
setCustomScenario((backtest.config as any).scenario);
|
||||||
|
setGlobalCustomScenario((backtest.config as any).scenario); // Also update global store for prefilling
|
||||||
|
setSelectedScenario('custom');
|
||||||
|
} else if (backtest.config.scenarioName) {
|
||||||
|
setSelectedScenario(backtest.config.scenarioName);
|
||||||
|
setShowCustomScenario(false);
|
||||||
|
}
|
||||||
|
|
||||||
setValue('timeframe', backtest.config.timeframe);
|
setValue('timeframe', backtest.config.timeframe);
|
||||||
setValue('botType', backtest.config.botType);
|
setValue('botType', backtest.config.botType);
|
||||||
setValue('cooldownPeriod', backtest.config.cooldownPeriod);
|
setValue('cooldownPeriod', backtest.config.cooldownPeriod);
|
||||||
@@ -203,11 +219,31 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
if (backtest.config.moneyManagement) {
|
if (backtest.config.moneyManagement) {
|
||||||
setShowCustomMoneyManagement(true);
|
setShowCustomMoneyManagement(true);
|
||||||
setCustomMoneyManagement(backtest.config.moneyManagement);
|
setCustomMoneyManagement(backtest.config.moneyManagement);
|
||||||
|
|
||||||
|
// Convert decimal values to percentages for UI display
|
||||||
|
const formattedMoneyManagement = {
|
||||||
|
...backtest.config.moneyManagement,
|
||||||
|
stopLoss: backtest.config.moneyManagement.stopLoss * 100,
|
||||||
|
takeProfit: backtest.config.moneyManagement.takeProfit * 100,
|
||||||
|
};
|
||||||
|
setGlobalCustomMoneyManagement(formattedMoneyManagement);
|
||||||
}
|
}
|
||||||
} else if (mode === 'backtest' && backtest) {
|
} else if (mode === 'backtest' && backtest) {
|
||||||
// Initialize from existing backtest for re-running
|
// Initialize from existing backtest for re-running
|
||||||
setValue('accountName', backtest.config.accountName);
|
setValue('accountName', backtest.config.accountName);
|
||||||
setValue('scenarioName', backtest.config.scenarioName || '');
|
setValue('scenarioName', backtest.config.scenarioName || '');
|
||||||
|
|
||||||
|
// Handle custom scenario from backtest
|
||||||
|
if ((backtest.config as any).scenario) {
|
||||||
|
setShowCustomScenario(true);
|
||||||
|
setCustomScenario((backtest.config as any).scenario);
|
||||||
|
setGlobalCustomScenario((backtest.config as any).scenario); // Also update global store for prefilling
|
||||||
|
setSelectedScenario('custom');
|
||||||
|
} else if (backtest.config.scenarioName) {
|
||||||
|
setSelectedScenario(backtest.config.scenarioName);
|
||||||
|
setShowCustomScenario(false);
|
||||||
|
}
|
||||||
|
|
||||||
setValue('timeframe', backtest.config.timeframe);
|
setValue('timeframe', backtest.config.timeframe);
|
||||||
setValue('botType', backtest.config.botType);
|
setValue('botType', backtest.config.botType);
|
||||||
setValue('cooldownPeriod', backtest.config.cooldownPeriod);
|
setValue('cooldownPeriod', backtest.config.cooldownPeriod);
|
||||||
@@ -243,6 +279,14 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
if (backtest.config.moneyManagement) {
|
if (backtest.config.moneyManagement) {
|
||||||
setShowCustomMoneyManagement(true);
|
setShowCustomMoneyManagement(true);
|
||||||
setCustomMoneyManagement(backtest.config.moneyManagement);
|
setCustomMoneyManagement(backtest.config.moneyManagement);
|
||||||
|
|
||||||
|
// Convert decimal values to percentages for UI display
|
||||||
|
const formattedMoneyManagement = {
|
||||||
|
...backtest.config.moneyManagement,
|
||||||
|
stopLoss: backtest.config.moneyManagement.stopLoss * 100,
|
||||||
|
takeProfit: backtest.config.moneyManagement.takeProfit * 100,
|
||||||
|
};
|
||||||
|
setGlobalCustomMoneyManagement(formattedMoneyManagement);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle risk management
|
// Handle risk management
|
||||||
@@ -274,6 +318,33 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
setValue('useForSignalFiltering', config.useForSignalFiltering ?? true);
|
setValue('useForSignalFiltering', config.useForSignalFiltering ?? true);
|
||||||
setValue('useForDynamicStopLoss', config.useForDynamicStopLoss ?? true);
|
setValue('useForDynamicStopLoss', config.useForDynamicStopLoss ?? true);
|
||||||
|
|
||||||
|
// Handle money management - if it exists, treat as custom for update mode
|
||||||
|
if (config.moneyManagement) {
|
||||||
|
setShowCustomMoneyManagement(true);
|
||||||
|
setCustomMoneyManagement(config.moneyManagement);
|
||||||
|
|
||||||
|
// Convert decimal values to percentages for UI display
|
||||||
|
const formattedMoneyManagement = {
|
||||||
|
...config.moneyManagement,
|
||||||
|
stopLoss: config.moneyManagement.stopLoss * 100,
|
||||||
|
takeProfit: config.moneyManagement.takeProfit * 100,
|
||||||
|
};
|
||||||
|
setGlobalCustomMoneyManagement(formattedMoneyManagement);
|
||||||
|
setSelectedMoneyManagement('custom'); // Set dropdown to show "custom"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle scenario - check if we have scenario data or just a name reference
|
||||||
|
if ((config as any).scenario) {
|
||||||
|
setShowCustomScenario(true);
|
||||||
|
setCustomScenario((config as any).scenario);
|
||||||
|
setGlobalCustomScenario((config as any).scenario); // Also update global store for prefilling
|
||||||
|
setSelectedScenario('custom'); // Set dropdown to show "custom"
|
||||||
|
} else if (config.scenarioName) {
|
||||||
|
setValue('scenarioName', config.scenarioName);
|
||||||
|
setSelectedScenario(config.scenarioName);
|
||||||
|
setShowCustomScenario(false);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle risk management
|
// Handle risk management
|
||||||
if (config.riskManagement) {
|
if (config.riskManagement) {
|
||||||
setValue('useCustomRiskManagement', true);
|
setValue('useCustomRiskManagement', true);
|
||||||
@@ -373,9 +444,11 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
if (e.target.value === 'custom') {
|
if (e.target.value === 'custom') {
|
||||||
setShowCustomMoneyManagement(true);
|
setShowCustomMoneyManagement(true);
|
||||||
setCustomMoneyManagement(undefined);
|
setCustomMoneyManagement(undefined);
|
||||||
|
setGlobalCustomMoneyManagement(null); // Clear global store when creating new custom
|
||||||
} else {
|
} else {
|
||||||
setShowCustomMoneyManagement(false);
|
setShowCustomMoneyManagement(false);
|
||||||
setCustomMoneyManagement(undefined);
|
setCustomMoneyManagement(undefined);
|
||||||
|
setGlobalCustomMoneyManagement(null); // Clear global store when switching away from custom
|
||||||
setSelectedMoneyManagement(e.target.value);
|
setSelectedMoneyManagement(e.target.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -384,9 +457,11 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
if (e.target.value === 'custom') {
|
if (e.target.value === 'custom') {
|
||||||
setShowCustomScenario(true);
|
setShowCustomScenario(true);
|
||||||
setCustomScenario(undefined);
|
setCustomScenario(undefined);
|
||||||
|
setGlobalCustomScenario(null); // Clear global store when creating new custom
|
||||||
} else {
|
} else {
|
||||||
setShowCustomScenario(false);
|
setShowCustomScenario(false);
|
||||||
setCustomScenario(undefined);
|
setCustomScenario(undefined);
|
||||||
|
setGlobalCustomScenario(null); // Clear global store when switching away from custom
|
||||||
setSelectedScenario(e.target.value);
|
setSelectedScenario(e.target.value);
|
||||||
setValue('scenarioName', e.target.value);
|
setValue('scenarioName', e.target.value);
|
||||||
}
|
}
|
||||||
@@ -612,7 +687,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* First Row: Account & Timeframe */}
|
{/* First Row: Account & Timeframe */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput label="Account" htmlFor="accountName">
|
<FormInput label="Account" htmlFor="accountName">
|
||||||
<select
|
<select
|
||||||
className="select select-bordered w-full"
|
className="select select-bordered w-full"
|
||||||
@@ -650,10 +725,11 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Second Row: Money Management & Bot Type */}
|
{/* Second Row: Money Management & Bot Type */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput label="Money Management" htmlFor="moneyManagement">
|
<FormInput label="Money Management" htmlFor="moneyManagement">
|
||||||
<select
|
<select
|
||||||
className="select select-bordered w-full"
|
className="select select-bordered w-full"
|
||||||
|
value={selectedMoneyManagement || (showCustomMoneyManagement ? 'custom' : '')}
|
||||||
onChange={onMoneyManagementChange}
|
onChange={onMoneyManagementChange}
|
||||||
>
|
>
|
||||||
{moneyManagements.length === 0 ? (
|
{moneyManagements.length === 0 ? (
|
||||||
@@ -704,6 +780,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
<select
|
<select
|
||||||
className="select select-bordered w-full"
|
className="select select-bordered w-full"
|
||||||
{...register('scenarioName')}
|
{...register('scenarioName')}
|
||||||
|
value={selectedScenario || (showCustomScenario ? 'custom' : '')}
|
||||||
onChange={onScenarioChange}
|
onChange={onScenarioChange}
|
||||||
>
|
>
|
||||||
{scenarios.length === 0 ? (
|
{scenarios.length === 0 ? (
|
||||||
@@ -854,7 +931,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
|
|
||||||
{/* Dates for backtests */}
|
{/* Dates for backtests */}
|
||||||
{mode === 'backtest' && (
|
{mode === 'backtest' && (
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput label="Start Date" htmlFor="startDate">
|
<FormInput label="Start Date" htmlFor="startDate">
|
||||||
<input
|
<input
|
||||||
type="date"
|
type="date"
|
||||||
@@ -899,13 +976,13 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
min="1"
|
min="1"
|
||||||
max="10"
|
max="10"
|
||||||
value={selectedLoopQuantity.toString()}
|
value={selectedLoopQuantity.toString()}
|
||||||
onChange={(e) => setLoopQuantity(Number(e.target.value))}
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setLoopQuantity(Number(e.target.value))}
|
||||||
/>
|
/>
|
||||||
</FormInput>
|
</FormInput>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Max Loss Streak & Max Position Time */}
|
{/* Max Loss Streak & Max Position Time */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput
|
<FormInput
|
||||||
label={
|
label={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -949,7 +1026,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Trading Options */}
|
{/* Trading Options */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput
|
<FormInput
|
||||||
label={
|
label={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -1179,7 +1256,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
</FormInput>
|
</FormInput>
|
||||||
|
|
||||||
{/* Risk Management Parameters Grid */}
|
{/* Risk Management Parameters Grid */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput
|
<FormInput
|
||||||
label={
|
label={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
@@ -1350,7 +1427,7 @@ const UnifiedTradingModal: React.FC<UnifiedTradingModalProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Checkboxes for Kelly and Expected Utility */}
|
{/* Checkboxes for Kelly and Expected Utility */}
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<FormInput
|
<FormInput
|
||||||
label={
|
label={
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ export type IFormInput = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IModalProps = {
|
export type IModalProps = {
|
||||||
showModal?: boolean | undefined
|
showModal: boolean
|
||||||
onSubmit?: React.FormEventHandler
|
onSubmit?: React.FormEventHandler
|
||||||
onClose?: React.FormEventHandler
|
onClose?: React.FormEventHandler
|
||||||
titleHeader?: string
|
titleHeader?: string
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import TradesModal from '../../components/mollecules/TradesModal/TradesModal'
|
|||||||
import {TradeChart, UnifiedTradingModal} from '../../components/organism'
|
import {TradeChart, UnifiedTradingModal} from '../../components/organism'
|
||||||
import type {BotType, MoneyManagement, Position, TradingBotResponse} from '../../generated/ManagingApi'
|
import type {BotType, MoneyManagement, Position, TradingBotResponse} from '../../generated/ManagingApi'
|
||||||
import {BotClient} from '../../generated/ManagingApi'
|
import {BotClient} from '../../generated/ManagingApi'
|
||||||
import type {IBotList} from '../../global/type'
|
import type {IBotList} from '../../global/type.tsx'
|
||||||
import MoneyManagementModal from '../settingsPage/moneymanagement/moneyManagementModal'
|
import MoneyManagementModal from '../settingsPage/moneymanagement/moneyManagementModal'
|
||||||
|
|
||||||
function baseBadgeClass(isOutlined = false) {
|
function baseBadgeClass(isOutlined = false) {
|
||||||
let classes = 'text-xs badge '
|
let classes = 'text-xs badge badge-sm transition-all duration-200 hover:scale-105 '
|
||||||
|
|
||||||
if (isOutlined) {
|
if (isOutlined) {
|
||||||
classes += 'badge-outline '
|
classes += 'badge-outline '
|
||||||
@@ -240,7 +240,7 @@ const BotList: React.FC<IBotList> = ({ list }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{list.map((bot: TradingBotResponse, index) => (
|
{list.map((bot: TradingBotResponse, index: number) => (
|
||||||
<div
|
<div
|
||||||
key={index.toString()}
|
key={index.toString()}
|
||||||
className="sm:w-1 md:w-1/2 xl:w-1/2 w-full p-2"
|
className="sm:w-1 md:w-1/2 xl:w-1/2 w-full p-2"
|
||||||
@@ -258,23 +258,36 @@ const BotList: React.FC<IBotList> = ({ list }) => {
|
|||||||
}
|
}
|
||||||
</figure>
|
</figure>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h2 className="card-title text-sm">
|
<div className="mb-4">
|
||||||
|
{/* Bot Name - Always on its own line */}
|
||||||
|
<h2 className="card-title text-sm mb-3">
|
||||||
{bot.config.ticker}
|
{bot.config.ticker}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{/* Badge Container - Responsive */}
|
||||||
|
<div className="flex flex-wrap gap-1 sm:gap-2">
|
||||||
|
{/* Info Badges */}
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
{getMoneyManagementBadge(bot.config.moneyManagement)}
|
{getMoneyManagementBadge(bot.config.moneyManagement)}
|
||||||
{getIsForWatchingBadge(bot.config.isForWatchingOnly, bot.identifier)}
|
{getIsForWatchingBadge(bot.config.isForWatchingOnly, bot.identifier)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Action Badges */}
|
||||||
|
<div className="flex flex-wrap gap-1">
|
||||||
{getToggleBotStatusBadge(bot.status, bot.identifier, bot.config.botType)}
|
{getToggleBotStatusBadge(bot.status, bot.identifier, bot.config.botType)}
|
||||||
{getUpdateBotBadge(bot)}
|
{getUpdateBotBadge(bot)}
|
||||||
{getManualPositionBadge(bot.identifier)}
|
{getManualPositionBadge(bot.identifier)}
|
||||||
{getDeleteBadge(bot.identifier)}
|
{getDeleteBadge(bot.identifier)}
|
||||||
</h2>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="columns-2">
|
<div className="columns-2">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<CardText
|
<CardText
|
||||||
title="Scenario"
|
title="Scenario"
|
||||||
content={bot.config.scenarioName}
|
content={bot.config.scenarioName ?? bot.config.scenario?.name}
|
||||||
></CardText>
|
></CardText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
import { useState } from 'react'
|
import {useState} from 'react'
|
||||||
import type { SubmitHandler } from 'react-hook-form'
|
import type {SubmitHandler} from 'react-hook-form'
|
||||||
import { useForm } from 'react-hook-form'
|
import {useForm} from 'react-hook-form'
|
||||||
|
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import { Modal, Toast } from '../../../components/mollecules'
|
import {Modal, Toast} from '../../../components/mollecules'
|
||||||
import type { Account } from '../../../generated/ManagingApi'
|
import type {Account} from '../../../generated/ManagingApi'
|
||||||
import {
|
import {AccountClient, AccountType, TradingExchanges,} from '../../../generated/ManagingApi'
|
||||||
AccountType,
|
import type {IAccountFormInput, IModalProps} from '../../../global/type.tsx'
|
||||||
AccountClient,
|
|
||||||
TradingExchanges,
|
|
||||||
} from '../../../generated/ManagingApi'
|
|
||||||
import type { IAccountFormInput, IModalProps } from '../../../global/type'
|
|
||||||
|
|
||||||
const AccountModal: React.FC<IModalProps> = ({ showModal, toggleModal }) => {
|
const AccountModal: React.FC<IModalProps> = ({ showModal, toggleModal }) => {
|
||||||
const [selectedExchange, setSelectedExchange] = useState<TradingExchanges>()
|
const [selectedExchange, setSelectedExchange] = useState<TradingExchanges>()
|
||||||
|
|||||||
Reference in New Issue
Block a user