redesign fully scaffolded and web login works
This commit is contained in:
94
gateway/knowledge/README.md
Normal file
94
gateway/knowledge/README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Dexorder Knowledge Base
|
||||
|
||||
This directory contains global knowledge documents that are automatically loaded into the RAG system as platform-wide knowledge (user_id="0").
|
||||
|
||||
## Structure
|
||||
|
||||
- **platform/**: Platform architecture and capabilities
|
||||
- **trading/**: Trading concepts and fundamentals
|
||||
- **indicators/**: Indicator development and usage
|
||||
- **strategies/**: Strategy development and patterns
|
||||
|
||||
## Document Format
|
||||
|
||||
Documents should be in Markdown format with:
|
||||
- Clear headings for chunking
|
||||
- Optional YAML frontmatter for tags
|
||||
- Code examples where relevant
|
||||
- Cross-references to other docs
|
||||
|
||||
### Example with Frontmatter
|
||||
|
||||
```markdown
|
||||
---
|
||||
tags: [trading, risk-management, position-sizing]
|
||||
---
|
||||
|
||||
# Risk Management
|
||||
|
||||
Content here...
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. At gateway startup, the DocumentLoader scans this directory
|
||||
2. Each markdown file is chunked by headers (max ~1000 tokens per chunk)
|
||||
3. Chunks are embedded using the configured embedding service
|
||||
4. Embeddings are stored in Qdrant with user_id="0" (global namespace)
|
||||
5. Content hash tracking enables incremental updates
|
||||
|
||||
## Updating Documents
|
||||
|
||||
### During Development
|
||||
- Edit markdown files
|
||||
- Restart gateway or call reload endpoint: `POST /admin/reload-knowledge`
|
||||
|
||||
### In Production
|
||||
- Update markdown files in git
|
||||
- Deploy new version
|
||||
- Gateway will detect changes and update vectors automatically
|
||||
|
||||
## RAG Integration
|
||||
|
||||
When users query the agent:
|
||||
1. Their query is embedded
|
||||
2. Qdrant searches both global (user_id="0") and user-specific vectors
|
||||
3. Relevant chunks from these docs are included in context
|
||||
4. LLM generates response with platform knowledge
|
||||
|
||||
## Adding New Documents
|
||||
|
||||
1. Create markdown file in appropriate subdirectory
|
||||
2. Use clear section headers (##, ###) for automatic chunking
|
||||
3. Include practical examples and code samples
|
||||
4. Add tags in frontmatter if using complex categorization
|
||||
5. Restart gateway or reload knowledge
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Keep chunks focused**: Each section should cover one topic
|
||||
- **Use examples**: Code samples and practical examples help
|
||||
- **Link concepts**: Reference other docs for deeper dives
|
||||
- **Update regularly**: Keep knowledge current with platform changes
|
||||
- **Test queries**: Verify RAG retrieves relevant chunks
|
||||
|
||||
## Maintenance
|
||||
|
||||
The DocumentLoader tracks:
|
||||
- Content hashes for change detection
|
||||
- Number of chunks per document
|
||||
- Last update timestamps
|
||||
|
||||
Check logs for load statistics:
|
||||
```
|
||||
Knowledge documents loaded: { loaded: 5, updated: 2, skipped: 3 }
|
||||
```
|
||||
|
||||
Monitor Qdrant collection stats:
|
||||
```
|
||||
GET /health
|
||||
{
|
||||
"qdrantVectors": 1234,
|
||||
"qdrantIndexed": 1234
|
||||
}
|
||||
```
|
||||
142
gateway/knowledge/indicators/indicator-development.md
Normal file
142
gateway/knowledge/indicators/indicator-development.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Indicator Development Guide
|
||||
|
||||
Custom indicators in Dexorder are Python functions that process OHLCV data and return signals or values.
|
||||
|
||||
## Indicator Structure
|
||||
|
||||
```python
|
||||
def my_indicator(df, **params):
|
||||
"""
|
||||
Calculate custom indicator
|
||||
|
||||
Args:
|
||||
df: DataFrame with columns [open, high, low, close, volume]
|
||||
**params: Indicator parameters
|
||||
|
||||
Returns:
|
||||
Series or DataFrame with indicator values
|
||||
"""
|
||||
# Implementation
|
||||
return result
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Simple Moving Average
|
||||
```python
|
||||
def sma(df, period=20):
|
||||
return df['close'].rolling(window=period).mean()
|
||||
```
|
||||
|
||||
### Exponential Moving Average
|
||||
```python
|
||||
def ema(df, period=20):
|
||||
return df['close'].ewm(span=period, adjust=False).mean()
|
||||
```
|
||||
|
||||
### RSI (Relative Strength Index)
|
||||
```python
|
||||
def rsi(df, period=14):
|
||||
delta = df['close'].diff()
|
||||
gain = delta.where(delta > 0, 0).rolling(window=period).mean()
|
||||
loss = -delta.where(delta < 0, 0).rolling(window=period).mean()
|
||||
rs = gain / loss
|
||||
return 100 - (100 / (1 + rs))
|
||||
```
|
||||
|
||||
### MACD
|
||||
```python
|
||||
def macd(df, fast=12, slow=26, signal=9):
|
||||
ema_fast = df['close'].ewm(span=fast).mean()
|
||||
ema_slow = df['close'].ewm(span=slow).mean()
|
||||
macd_line = ema_fast - ema_slow
|
||||
signal_line = macd_line.ewm(span=signal).mean()
|
||||
histogram = macd_line - signal_line
|
||||
|
||||
return pd.DataFrame({
|
||||
'macd': macd_line,
|
||||
'signal': signal_line,
|
||||
'histogram': histogram
|
||||
})
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Data Handling
|
||||
- Always validate input DataFrame has required columns
|
||||
- Handle NaN values appropriately
|
||||
- Use `.copy()` to avoid modifying original data
|
||||
- Consider edge cases (not enough data, etc.)
|
||||
|
||||
### Performance
|
||||
- Vectorize operations when possible (avoid loops)
|
||||
- Use pandas/numpy built-in functions
|
||||
- Cache expensive calculations
|
||||
- Test on large datasets
|
||||
|
||||
### Parameters
|
||||
- Provide sensible defaults
|
||||
- Document parameter ranges
|
||||
- Validate parameter values
|
||||
- Consider optimization bounds
|
||||
|
||||
### Testing
|
||||
```python
|
||||
def test_indicator():
|
||||
# Create sample data
|
||||
df = pd.DataFrame({
|
||||
'close': [100, 102, 101, 103, 105]
|
||||
})
|
||||
|
||||
# Test calculation
|
||||
result = my_indicator(df, param=10)
|
||||
|
||||
# Validate output
|
||||
assert not result.isna().all()
|
||||
assert len(result) == len(df)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Look-Ahead Bias
|
||||
Never use future data:
|
||||
```python
|
||||
# WRONG - uses future data
|
||||
df['signal'] = df['close'].shift(-1) > df['close']
|
||||
|
||||
# CORRECT - only past data
|
||||
df['signal'] = df['close'] > df['close'].shift(1)
|
||||
```
|
||||
|
||||
### Repainting
|
||||
Indicator values should not change for closed bars:
|
||||
```python
|
||||
# Ensure calculations are based on closed candles
|
||||
# Avoid using unstable data sources
|
||||
```
|
||||
|
||||
### Overfitting
|
||||
- Don't optimize on same data you test on
|
||||
- Use separate train/validation/test sets
|
||||
- Walk-forward analysis for robustness
|
||||
- Simple is often better than complex
|
||||
|
||||
## Integration with Strategies
|
||||
|
||||
Indicators are used in strategy signals:
|
||||
```python
|
||||
def my_strategy(df):
|
||||
# Calculate indicators
|
||||
df['rsi'] = rsi(df, period=14)
|
||||
df['sma_fast'] = sma(df, period=20)
|
||||
df['sma_slow'] = sma(df, period=50)
|
||||
|
||||
# Generate signals
|
||||
df['signal'] = 0
|
||||
df.loc[(df['rsi'] < 30) & (df['sma_fast'] > df['sma_slow']), 'signal'] = 1
|
||||
df.loc[(df['rsi'] > 70) & (df['sma_fast'] < df['sma_slow']), 'signal'] = -1
|
||||
|
||||
return df
|
||||
```
|
||||
|
||||
Store indicators in your git repository under `indicators/` directory.
|
||||
71
gateway/knowledge/platform/agent-system.md
Normal file
71
gateway/knowledge/platform/agent-system.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Agent System Architecture
|
||||
|
||||
The Dexorder AI platform uses a sophisticated agent harness that orchestrates between user interactions, LLM models, and user-specific tools.
|
||||
|
||||
## Core Components
|
||||
|
||||
### Gateway
|
||||
Multi-channel gateway supporting:
|
||||
- WebSocket connections for web/mobile
|
||||
- Telegram integration
|
||||
- Real-time event streaming
|
||||
|
||||
### Agent Harness
|
||||
Stateless orchestrator that:
|
||||
1. Fetches context from user's MCP server
|
||||
2. Routes to appropriate LLM model based on license
|
||||
3. Calls LLM with embedded context
|
||||
4. Routes tool calls to user's MCP or platform tools
|
||||
5. Saves conversation history back to MCP
|
||||
|
||||
### Memory Architecture
|
||||
Three-tier storage system:
|
||||
- **Redis**: Hot state for active sessions and checkpoints
|
||||
- **Qdrant**: Vector search for RAG and semantic memory
|
||||
- **Iceberg**: Cold storage for durable conversations and analytics
|
||||
|
||||
### User Context
|
||||
Every interaction includes:
|
||||
- User ID and license information
|
||||
- Active channel (websocket, telegram, etc.)
|
||||
- Channel capabilities (markdown, images, buttons)
|
||||
- Conversation history
|
||||
- Relevant memories from RAG
|
||||
- Workspace state
|
||||
|
||||
## Skills vs Subagents
|
||||
|
||||
### Skills
|
||||
Self-contained capabilities for specific tasks:
|
||||
- Market analysis
|
||||
- Strategy validation
|
||||
- Indicator development
|
||||
- Defined in markdown + TypeScript
|
||||
- Use when task is well-defined and scoped
|
||||
|
||||
### Subagents
|
||||
Specialized agents with dedicated memory:
|
||||
- Code reviewer with review guidelines
|
||||
- Risk analyzer with risk models
|
||||
- Multi-file knowledge base
|
||||
- Custom system prompts
|
||||
- Use when domain expertise is needed
|
||||
|
||||
## Global vs User Memory
|
||||
|
||||
### Global Memory (user_id="0")
|
||||
Platform-wide knowledge available to all users:
|
||||
- Trading concepts and terminology
|
||||
- Platform capabilities
|
||||
- Indicator documentation
|
||||
- Strategy patterns
|
||||
- Best practices
|
||||
|
||||
### User Memory
|
||||
Personal context specific to each user:
|
||||
- Conversation history
|
||||
- Preferences and trading style
|
||||
- Custom indicators and strategies
|
||||
- Workspace state
|
||||
|
||||
All RAG queries automatically search both global and user-specific memories.
|
||||
88
gateway/knowledge/platform/mcp-integration.md
Normal file
88
gateway/knowledge/platform/mcp-integration.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Model Context Protocol (MCP) Integration
|
||||
|
||||
Dexorder uses the Model Context Protocol for user-specific tool execution and state management.
|
||||
|
||||
## Container Architecture
|
||||
|
||||
Each user has a dedicated Kubernetes pod running:
|
||||
- **Agent Container**: Python environment with conda packages
|
||||
- **Lifecycle Sidecar**: Manages container lifecycle and communication
|
||||
- **Persistent Storage**: User's git repository with indicators/strategies
|
||||
|
||||
## Authentication Modes
|
||||
|
||||
Three MCP authentication modes:
|
||||
|
||||
### 1. Public Mode (Free Tier)
|
||||
- No authentication required
|
||||
- Container creates anonymous session
|
||||
- Limited to read-only resources
|
||||
- Session expires after timeout
|
||||
|
||||
### 2. Gateway Auth Mode (Standard)
|
||||
- Gateway authenticates user
|
||||
- Passes verified user ID to container
|
||||
- Container trusts gateway's authentication
|
||||
- Full access to user's tools and data
|
||||
|
||||
### 3. Direct Auth Mode (Enterprise)
|
||||
- User authenticates directly with container
|
||||
- Gateway forwards encrypted credentials
|
||||
- Container validates credentials independently
|
||||
- Highest security for sensitive operations
|
||||
|
||||
## MCP Resources
|
||||
|
||||
The container exposes standard resources:
|
||||
|
||||
### context://user-profile
|
||||
User preferences and trading style
|
||||
|
||||
### context://conversation-summary
|
||||
Recent conversation context and history
|
||||
|
||||
### context://workspace-state
|
||||
Current chart, indicators, and analysis state
|
||||
|
||||
### context://system-prompt
|
||||
User's custom agent instructions
|
||||
|
||||
### indicators://list
|
||||
Available indicators with signatures
|
||||
|
||||
### strategies://list
|
||||
User's trading strategies
|
||||
|
||||
## Tool Execution Flow
|
||||
|
||||
1. User sends message to gateway
|
||||
2. Gateway queries user's MCP resources for context
|
||||
3. LLM generates response with tool calls
|
||||
4. Gateway routes tool calls:
|
||||
- Platform tools → handled by gateway
|
||||
- User tools → proxied to MCP container
|
||||
5. Tool results returned to LLM
|
||||
6. Final response sent to user
|
||||
7. Conversation saved to MCP container
|
||||
|
||||
## Container Lifecycle
|
||||
|
||||
### Startup
|
||||
1. Gateway receives user connection
|
||||
2. Checks if container exists
|
||||
3. Creates pod if needed (cold start ~5-10s)
|
||||
4. Waits for container ready
|
||||
5. Establishes MCP connection
|
||||
|
||||
### Active
|
||||
- Container stays alive during active session
|
||||
- Receives tool calls via MCP
|
||||
- Maintains workspace state
|
||||
- Saves files to persistent storage
|
||||
|
||||
### Shutdown
|
||||
- Free users: timeout after 15 minutes idle
|
||||
- Paid users: longer timeout based on license
|
||||
- Graceful shutdown saves state
|
||||
- Persistent storage retained
|
||||
- Fast restart on next connection
|
||||
188
gateway/knowledge/strategies/strategy-development.md
Normal file
188
gateway/knowledge/strategies/strategy-development.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Strategy Development Guide
|
||||
|
||||
Trading strategies in Dexorder define entry/exit rules and position management logic.
|
||||
|
||||
## Strategy Structure
|
||||
|
||||
```python
|
||||
class Strategy:
|
||||
def __init__(self, **params):
|
||||
"""Initialize strategy with parameters"""
|
||||
self.params = params
|
||||
|
||||
def generate_signals(self, df):
|
||||
"""
|
||||
Generate trading signals
|
||||
|
||||
Args:
|
||||
df: DataFrame with OHLCV + indicator columns
|
||||
|
||||
Returns:
|
||||
DataFrame with 'signal' column:
|
||||
1 = long entry
|
||||
-1 = short entry
|
||||
0 = no action
|
||||
"""
|
||||
pass
|
||||
|
||||
def calculate_position_size(self, capital, price, risk_pct):
|
||||
"""Calculate position size based on risk"""
|
||||
pass
|
||||
|
||||
def get_stop_loss(self, entry_price, direction):
|
||||
"""Calculate stop loss level"""
|
||||
pass
|
||||
|
||||
def get_take_profit(self, entry_price, direction):
|
||||
"""Calculate take profit level"""
|
||||
pass
|
||||
```
|
||||
|
||||
## Example: Simple Moving Average Crossover
|
||||
|
||||
```python
|
||||
class SMACrossoverStrategy:
|
||||
def __init__(self, fast_period=20, slow_period=50, risk_pct=0.02):
|
||||
self.fast_period = fast_period
|
||||
self.slow_period = slow_period
|
||||
self.risk_pct = risk_pct
|
||||
|
||||
def generate_signals(self, df):
|
||||
# Calculate moving averages
|
||||
df['sma_fast'] = df['close'].rolling(self.fast_period).mean()
|
||||
df['sma_slow'] = df['close'].rolling(self.slow_period).mean()
|
||||
|
||||
# Generate signals
|
||||
df['signal'] = 0
|
||||
|
||||
# Long when fast crosses above slow
|
||||
df.loc[
|
||||
(df['sma_fast'] > df['sma_slow']) &
|
||||
(df['sma_fast'].shift(1) <= df['sma_slow'].shift(1)),
|
||||
'signal'
|
||||
] = 1
|
||||
|
||||
# Short when fast crosses below slow
|
||||
df.loc[
|
||||
(df['sma_fast'] < df['sma_slow']) &
|
||||
(df['sma_fast'].shift(1) >= df['sma_slow'].shift(1)),
|
||||
'signal'
|
||||
] = -1
|
||||
|
||||
return df
|
||||
|
||||
def calculate_position_size(self, capital, price, atr):
|
||||
# Risk-based position sizing
|
||||
risk_amount = capital * self.risk_pct
|
||||
stop_distance = 2 * atr
|
||||
position_size = risk_amount / stop_distance
|
||||
return position_size
|
||||
|
||||
def get_stop_loss(self, entry_price, direction, atr):
|
||||
if direction == 1: # Long
|
||||
return entry_price - (2 * atr)
|
||||
else: # Short
|
||||
return entry_price + (2 * atr)
|
||||
|
||||
def get_take_profit(self, entry_price, direction, atr):
|
||||
if direction == 1: # Long
|
||||
return entry_price + (4 * atr) # 2:1 risk/reward
|
||||
else: # Short
|
||||
return entry_price - (4 * atr)
|
||||
```
|
||||
|
||||
## Strategy Components
|
||||
|
||||
### Signal Generation
|
||||
Entry conditions based on:
|
||||
- Indicator crossovers
|
||||
- Price patterns
|
||||
- Volume confirmation
|
||||
- Multiple timeframe confluence
|
||||
|
||||
### Risk Management
|
||||
Essential elements:
|
||||
- **Position Sizing**: Based on account risk percentage
|
||||
- **Stop Losses**: ATR-based or support/resistance
|
||||
- **Take Profits**: Multiple targets or trailing stops
|
||||
- **Max Positions**: Limit concurrent trades
|
||||
|
||||
### Filters
|
||||
Reduce false signals:
|
||||
- **Trend Filter**: Only trade with the trend
|
||||
- **Volatility Filter**: Avoid low volatility periods
|
||||
- **Time Filter**: Specific trading hours
|
||||
- **Volume Filter**: Minimum volume requirements
|
||||
|
||||
### Exit Rules
|
||||
Multiple exit types:
|
||||
- **Stop Loss**: Protect capital
|
||||
- **Take Profit**: Lock in gains
|
||||
- **Trailing Stop**: Follow profitable moves
|
||||
- **Time Exit**: Close at end of period
|
||||
- **Signal Exit**: Opposite signal
|
||||
|
||||
## Backtesting Considerations
|
||||
|
||||
### Data Quality
|
||||
- Use clean, validated data
|
||||
- Handle missing data appropriately
|
||||
- Account for survivorship bias
|
||||
- Include realistic spreads and slippage
|
||||
|
||||
### Performance Metrics
|
||||
Track key metrics:
|
||||
- **Total Return**: Cumulative profit/loss
|
||||
- **Sharpe Ratio**: Risk-adjusted returns
|
||||
- **Max Drawdown**: Largest peak-to-trough decline
|
||||
- **Win Rate**: Percentage of profitable trades
|
||||
- **Profit Factor**: Gross profit / gross loss
|
||||
- **Expectancy**: Average $ per trade
|
||||
|
||||
### Validation
|
||||
Prevent overfitting:
|
||||
- **Train/Test Split**: 70/30 or 60/40
|
||||
- **Walk-Forward**: Rolling windows
|
||||
- **Out-of-Sample**: Test on recent unseen data
|
||||
- **Monte Carlo**: Randomize trade order
|
||||
- **Paper Trading**: Live validation
|
||||
|
||||
## Common Strategy Types
|
||||
|
||||
### Trend Following
|
||||
Follow sustained price movements:
|
||||
- Moving average crossovers
|
||||
- Breakout strategies
|
||||
- Trend channels
|
||||
- Works best in trending markets
|
||||
|
||||
### Mean Reversion
|
||||
Profit from price returning to average:
|
||||
- Bollinger Band reversals
|
||||
- RSI extremes
|
||||
- Statistical arbitrage
|
||||
- Works best in ranging markets
|
||||
|
||||
### Momentum
|
||||
Trade in direction of strong moves:
|
||||
- Relative strength
|
||||
- Price acceleration
|
||||
- Volume surges
|
||||
- Breakout confirmation
|
||||
|
||||
### Arbitrage
|
||||
Exploit price discrepancies:
|
||||
- Cross-exchange spreads
|
||||
- Funding rate arbitrage
|
||||
- Statistical pairs trading
|
||||
- Requires low latency
|
||||
|
||||
## Integration with Platform
|
||||
|
||||
Store strategies in your git repository under `strategies/` directory.
|
||||
|
||||
Test using the backtesting tools provided by the platform.
|
||||
|
||||
Deploy live strategies through the execution engine with proper risk controls.
|
||||
|
||||
Monitor performance and adjust parameters as market conditions change.
|
||||
72
gateway/knowledge/trading/technical-analysis.md
Normal file
72
gateway/knowledge/trading/technical-analysis.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Technical Analysis Fundamentals
|
||||
|
||||
Technical analysis is the study of historical price and volume data to identify patterns and predict future market movements.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Price Action
|
||||
Raw price movement without indicators:
|
||||
- Support and resistance levels
|
||||
- Trend lines and channels
|
||||
- Chart patterns (head and shoulders, double tops, etc.)
|
||||
- Candlestick patterns
|
||||
|
||||
### Trends
|
||||
Markets move in trends:
|
||||
- **Uptrend**: Higher highs and higher lows
|
||||
- **Downtrend**: Lower highs and lower lows
|
||||
- **Sideways**: Range-bound consolidation
|
||||
- Trend strength measured by consistency
|
||||
|
||||
### Volume
|
||||
Trading volume confirms price movements:
|
||||
- High volume confirms trends
|
||||
- Low volume suggests weak moves
|
||||
- Volume precedes price
|
||||
- Divergences signal reversals
|
||||
|
||||
## Common Indicators
|
||||
|
||||
### Trend Indicators
|
||||
- **Moving Averages**: SMA, EMA, WMA
|
||||
- **MACD**: Trend and momentum
|
||||
- **ADX**: Trend strength
|
||||
- **Parabolic SAR**: Trend direction
|
||||
|
||||
### Momentum Indicators
|
||||
- **RSI**: Overbought/oversold conditions (0-100)
|
||||
- **Stochastic**: Fast vs slow momentum
|
||||
- **CCI**: Cyclical trends
|
||||
- **Williams %R**: Momentum oscillator
|
||||
|
||||
### Volatility Indicators
|
||||
- **Bollinger Bands**: Price envelope around MA
|
||||
- **ATR**: Average True Range for volatility
|
||||
- **Keltner Channels**: ATR-based bands
|
||||
- **Donchian Channels**: High/low breakouts
|
||||
|
||||
### Volume Indicators
|
||||
- **OBV**: On Balance Volume
|
||||
- **VWAP**: Volume Weighted Average Price
|
||||
- **Volume Profile**: Price levels by volume
|
||||
- **Chaikin Money Flow**: Volume pressure
|
||||
|
||||
## Timeframes
|
||||
|
||||
Different timeframes for different strategies:
|
||||
- **Scalping**: 1m, 5m charts
|
||||
- **Day Trading**: 5m, 15m, 1h charts
|
||||
- **Swing Trading**: 4h, 1D charts
|
||||
- **Position Trading**: 1D, 1W charts
|
||||
|
||||
Always analyze multiple timeframes for context.
|
||||
|
||||
## Risk Management
|
||||
|
||||
Essential principles:
|
||||
- **Position Sizing**: Risk 1-2% per trade
|
||||
- **Stop Losses**: Define exit before entry
|
||||
- **Risk/Reward**: Minimum 1:2 ratio
|
||||
- **Diversification**: Multiple uncorrelated positions
|
||||
|
||||
Never trade without a plan and defined risk parameters.
|
||||
Reference in New Issue
Block a user