Skip to content

Latest commit

 

History

History
1143 lines (861 loc) · 36.9 KB

File metadata and controls

1143 lines (861 loc) · 36.9 KB

📚 Документация для разработчика - Crypto Spread

📖 Оглавление

  1. Введение
  2. Что такое Laravel?
  3. Архитектура проекта
  4. Структура проекта
  5. Детальное описание компонентов
  6. Поток данных
  7. База данных
  8. Как запустить проект
  9. Как добавить новую функциональность
  10. Часто задаваемые вопросы

Введение

Crypto Spread - это Laravel-приложение для автоматического обнаружения арбитражных возможностей на криптовалютных биржах. Проект мониторит цены на разных биржах (Binance, OKX, Bybit) и отправляет уведомления в Telegram, когда обнаруживает возможность заработать на разнице цен.

Что такое арбитраж?

Арбитраж - это покупка актива на одной бирже по низкой цене и одновременная продажа на другой бирже по более высокой цене. Разница в ценах (минус комиссии) - это прибыль.

Пример:

  • BTC стоит $50,000 на Binance
  • BTC стоит $50,500 на OKX
  • Потенциальная прибыль: $500 (минус комиссии бирж)

Что такое Laravel?

Если вы знаете PHP, но не знакомы с Laravel, вот краткое объяснение:

Laravel - это PHP-фреймворк, который упрощает разработку веб-приложений. Основные концепции:

1. MVC (Model-View-Controller)

  • Model (app/Models/) - работа с базой данных
  • View (resources/views/) - HTML шаблоны
  • Controller (app/Http/Controllers/) - обработка запросов

В нашем проекте мы используем в основном Models и Services (бизнес-логика).

2. Eloquent ORM

Вместо SQL запросов вы пишете PHP код:

// Вместо: SELECT * FROM users WHERE telegram_id = '123'
$user = User::where('telegram_id', '123')->first();

// Вместо: INSERT INTO prices ...
Price::create([
    'exchange_id' => 1,
    'symbol' => 'BTC/USDT',
    'price' => 50000
]);

3. Dependency Injection (DI)

Laravel автоматически передает зависимости в конструкторы:

// Laravel автоматически создаст TelegramBotService и передаст его
public function __construct(TelegramBotService $telegramService) {
    $this->telegramService = $telegramService;
}

4. Jobs (Очереди)

Асинхронное выполнение задач через очереди (Redis):

// Задача будет выполнена в фоне
FetchPricesJob::dispatch('BTC/USDT');

5. Artisan Commands

Консольные команды для выполнения задач:

php artisan telegram:bot          # Запустить Telegram бота
php artisan arbitrage:fetch-prices # Запустить фетчер цен

Архитектура проекта

Проект состоит из нескольких независимых компонентов, которые работают вместе:

┌─────────────────┐
│  Price Fetcher  │ → Получает цены с бирж
│   (Command)     │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ FetchPricesJob  │ → Сохраняет цены в БД
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│CheckArbitrageJob│ → Анализирует цены
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ ArbitrageService│ → Находит арбитраж
└────────┬────────┘
         │
         ▼
┌──────────────────────┐
│SendTelegramNotifJob  │ → Отправляет уведомления
└────────┬─────────────┘
         │
         ▼
┌─────────────────┐
│ Telegram Bot    │ → Пользователь получает сообщение
│   (Command)     │
└─────────────────┘

Структура проекта

📁 app/ - Основной код приложения

app/Models/ - Модели (работа с БД)

Что такое Model? Model - это класс, который представляет таблицу в базе данных. Каждая модель соответствует одной таблице.

  • User.php - Пользователи Telegram бота
  • Exchange.php - Криптовалютные биржи
  • Price.php - История цен с бирж
  • Alert.php - Обнаруженные арбитражные возможности

app/Services/ - Бизнес-логика

Что такое Service? Service - это класс, который содержит бизнес-логику (не связанную напрямую с БД или HTTP).

  • ArbitrageService.php - Логика обнаружения арбитража
  • TelegramBotService.php - Работа с Telegram API
  • Exchange/ - Сервисы для работы с биржами
    • ExchangeServiceInterface.php - Интерфейс (контракт)
    • BinanceService.php - Интеграция с Binance
    • OKXService.php - Интеграция с OKX
    • BybitService.php - Интеграция с Bybit
    • ExchangeServiceFactory.php - Фабрика для создания сервисов

app/Jobs/ - Фоновые задачи

Что такое Job? Job - это задача, которая выполняется асинхронно через очередь (Redis). Полезно для долгих операций.

  • FetchPricesJob.php - Получение цен с бирж
  • CheckArbitrageJob.php - Проверка арбитражных возможностей
  • SendTelegramNotificationJob.php - Отправка уведомлений

app/Console/Commands/ - Консольные команды

Что такое Command? Command - это команда, которую можно запустить из терминала через php artisan.

  • TelegramBotCommand.php - Запуск Telegram бота
  • RunPriceFetcherCommand.php - Запуск фетчера цен

📁 database/ - База данных

  • migrations/ - Миграции (схема БД)
  • seeders/ - Сидеры (начальные данные)

📁 config/ - Конфигурация

  • services.php - Настройки внешних сервисов (Telegram)
  • database.php - Настройки БД
  • queue.php - Настройки очередей

📁 routes/ - Маршруты

  • web.php - HTTP маршруты
  • console.php - Консольные команды

Детальное описание компонентов

1. Модели (Models)

User.php - Пользователи

class User extends Model {
    protected $fillable = [
        'telegram_id',      // ID пользователя в Telegram
        'password_hash',    // Хеш пароля (bcrypt)
        'is_active',        // Активен ли пользователь
        'alerts_enabled',   // Включены ли уведомления
    ];
}

Что делает:

  • Хранит информацию о пользователях Telegram бота
  • Метод verifyPassword() - проверяет пароль

Пример использования:

// Найти пользователя по Telegram ID
$user = User::where('telegram_id', '123456789')->first();

// Создать нового пользователя
$user = User::create([
    'telegram_id' => '123456789',
    'password_hash' => Hash::make('my_password'),
    'is_active' => true,
    'alerts_enabled' => true,
]);

// Обновить настройки
$user->update(['alerts_enabled' => false]);

Exchange.php - Биржи

class Exchange extends Model {
    protected $fillable = [
        'name',      // Название биржи (Binance, OKX, Bybit)
        'api_url',   // URL API биржи
        'priority',  // Приоритет (1 = самый важный)
        'is_active', // Активна ли биржа
    ];
}

Что делает:

  • Хранит информацию о биржах
  • Метод getLatestPrice($symbol) - получает последнюю цену для символа
  • Связь prices() - все цены этой биржи

Пример использования:

// Получить все активные биржи
$exchanges = Exchange::where('is_active', true)->get();

// Получить последнюю цену BTC/USDT на Binance
$exchange = Exchange::where('name', 'Binance')->first();
$price = $exchange->getLatestPrice('BTC/USDT');

Price.php - Цены

class Price extends Model {
    protected $fillable = [
        'exchange_id', // ID биржи
        'symbol',      // Пара (BTC/USDT)
        'price',       // Цена
    ];
}

Что делает:

  • Хранит историю цен с бирж
  • Связь exchange() - биржа, которой принадлежит цена

Пример использования:

// Сохранить новую цену
Price::create([
    'exchange_id' => 1,
    'symbol' => 'BTC/USDT',
    'price' => 50000.50,
]);

// Получить все цены для BTC/USDT
$prices = Price::where('symbol', 'BTC/USDT')
    ->orderBy('created_at', 'desc')
    ->get();

Alert.php - Арбитражные сигналы

class Alert extends Model {
    protected $fillable = [
        'symbol',         // Пара (BTC/USDT)
        'buy_exchange',   // Биржа для покупки
        'sell_exchange',  // Биржа для продажи
        'buy_price',      // Цена покупки
        'sell_price',     // Цена продажи
        'profit_percent', // Процент прибыли
        'notified',       // Отправлено ли уведомление
    ];
}

Что делает:

  • Хранит обнаруженные арбитражные возможности

Пример использования:

// Создать новый сигнал
$alert = Alert::create([
    'symbol' => 'BTC/USDT',
    'buy_exchange' => 'Binance',
    'sell_exchange' => 'OKX',
    'buy_price' => 50000,
    'sell_price' => 50500,
    'profit_percent' => 0.8,
    'notified' => false,
]);

2. Сервисы (Services)

ArbitrageService.php - Обнаружение арбитража

Что делает: Этот сервис анализирует цены с разных бирж и находит арбитражные возможности.

Основной метод: checkArbitrage($symbol)

public function checkArbitrage(string $symbol): ?Alert

Как работает:

  1. Получает все активные биржи из БД
  2. Для каждой биржи получает последнюю цену (не старше 1 минуты)
  3. Находит самую низкую цену (где покупать) и самую высокую (где продавать)
  4. Вычисляет процент прибыли: ((sell_price - buy_price) / buy_price) * 100
  5. Вычитает комиссии бирж (0.2% = 0.1% на покупку + 0.1% на продажу)
  6. Если прибыль >= 0.5%, создает Alert

Константы:

  • MIN_PROFIT_PERCENT = 0.5 - минимальный процент прибыли
  • EXCHANGE_FEE_PERCENT = 0.1 - комиссия одной биржи

Пример использования:

$arbitrageService = new ArbitrageService();
$alert = $arbitrageService->checkArbitrage('BTC/USDT');

if ($alert) {
    echo "Найдена возможность! Прибыль: {$alert->profit_percent}%";
}

TelegramBotService.php - Работа с Telegram API

Что делает: Этот сервис отправляет сообщения в Telegram и получает обновления от бота.

Основные методы:

  1. sendMessage($chatId, $message) - Отправить сообщение
  2. getUpdates($offset) - Получить новые сообщения
  3. formatArbitrageAlert($alert) - Форматировать сообщение об арбитраже

Как работает:

Использует HTTP клиент (Guzzle) для отправки запросов к Telegram API:

  • https://api.telegram.org/bot{TOKEN}/sendMessage - отправка сообщения
  • https://api.telegram.org/bot{TOKEN}/getUpdates - получение обновлений

Пример использования:

$telegramService = new TelegramBotService();

// Отправить сообщение
$telegramService->sendMessage('123456789', 'Привет!');

// Получить новые сообщения
$updates = $telegramService->getUpdates();

ExchangeServiceInterface.php - Интерфейс для бирж

Что такое Interface? Интерфейс - это "контракт", который определяет, какие методы должен иметь класс. Все сервисы бирж должны реализовывать этот интерфейс.

interface ExchangeServiceInterface {
    public function getTickerPrice(string $symbol): ?float;
    public function getName(): string;
}

Зачем это нужно? Это позволяет использовать любой сервис биржи одинаково, не зная конкретной реализации:

// Работает с любой биржей одинаково
$service = ExchangeServiceFactory::create('Binance');
$price = $service->getTickerPrice('BTC/USDT');

BinanceService.php - Интеграция с Binance

Что делает: Получает цены с API Binance.

Как работает:

  1. Преобразует символ BTC/USDTBTCUSDT (формат Binance)
  2. Отправляет GET запрос: https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT
  3. Парсит ответ и возвращает цену

Пример ответа от API:

{
  "symbol": "BTCUSDT",
  "price": "50000.50"
}

Аналогично работают:

  • OKXService.php - для OKX
  • BybitService.php - для Bybit

ExchangeServiceFactory.php - Фабрика сервисов

Что такое Factory? Фабрика - это паттерн проектирования, который создает объекты.

Что делает: Создает нужный сервис биржи по имени:

// Создать сервис Binance
$service = ExchangeServiceFactory::create('Binance');

// Создать сервис из модели Exchange
$exchange = Exchange::find(1);
$service = ExchangeServiceFactory::createFromModel($exchange);

Зачем это нужно? Вместо того чтобы писать:

if ($exchange->name === 'Binance') {
    $service = new BinanceService();
} elseif ($exchange->name === 'OKX') {
    $service = new OKXService();
}

Мы просто пишем:

$service = ExchangeServiceFactory::createFromModel($exchange);

3. Jobs (Фоновые задачи)

FetchPricesJob.php - Получение цен

Что делает: Получает цены со всех активных бирж и сохраняет их в БД.

Как работает:

  1. Получает все активные биржи из БД
  2. Для каждой биржи:
    • Создает сервис через Factory
    • Получает цену через API
    • Сохраняет цену в БД
    • Делает паузу 200ms (чтобы не превысить лимиты API)

Когда выполняется: Вызывается из команды RunPriceFetcherCommand каждые N секунд.

Пример использования:

// Добавить задачу в очередь
FetchPricesJob::dispatch('BTC/USDT');

// Выполнить сразу (синхронно)
FetchPricesJob::dispatchSync('BTC/USDT');

CheckArbitrageJob.php - Проверка арбитража

Что делает: Проверяет наличие арбитражных возможностей и отправляет уведомления.

Как работает:

  1. Вызывает ArbitrageService::checkArbitrage()
  2. Если найдена возможность:
    • Получает всех активных пользователей с включенными уведомлениями
    • Для каждого пользователя создает задачу SendTelegramNotificationJob

Когда выполняется: Вызывается из команды RunPriceFetcherCommand после получения цен.

SendTelegramNotificationJob.php - Отправка уведомлений

Что делает: Отправляет уведомление об арбитраже конкретному пользователю.

Как работает:

  1. Получает Alert из БД
  2. Проверяет, не отправлено ли уже уведомление
  3. Форматирует сообщение через TelegramBotService::formatArbitrageAlert()
  4. Отправляет сообщение через TelegramBotService::sendMessage()
  5. Помечает Alert как notified = true

Повторы: Если отправка не удалась, задача повторится до 3 раз ($tries = 3).


4. Commands (Консольные команды)

TelegramBotCommand.php - Telegram бот

Что делает: Запускает Telegram бота, который обрабатывает команды пользователей.

Как работает:

  1. Запускается бесконечный цикл (while (true))
  2. Каждую секунду получает новые сообщения через getUpdates()
  3. Обрабатывает команды:
    • /start - Приветствие
    • /set_password YOUR_PASSWORD - Аутентификация
    • /alerts_on - Включить уведомления
    • /alerts_off - Выключить уведомления
    • /history - Показать последние 10 сигналов

Запуск:

php artisan telegram:bot

Как обрабатываются команды:

switch ($command) {
    case '/start':
        $this->handleStart($chatId);
        break;
    case '/set_password':
        $this->handleSetPassword($chatId, $text);
        break;
    // ...
}

RunPriceFetcherCommand.php - Фетчер цен

Что делает: Запускает процесс получения цен и проверки арбитража.

Как работает:

  1. Запускается бесконечный цикл
  2. Каждые N секунд (по умолчанию 5):
    • Добавляет задачу FetchPricesJob в очередь
    • Ждет 1 секунду (чтобы цены успели сохраниться)
    • Добавляет задачу CheckArbitrageJob в очередь

Запуск:

# Мониторить BTC/USDT каждые 5 секунд
php artisan arbitrage:fetch-prices BTC/USDT --interval=5

# Мониторить ETH/USDT каждые 10 секунд
php artisan arbitrage:fetch-prices ETH/USDT --interval=10

Поток данных

Полный цикл работы системы:

1. Запуск команды: php artisan arbitrage:fetch-prices BTC/USDT
   │
   ▼
2. RunPriceFetcherCommand каждые 5 секунд:
   │
   ├─→ FetchPricesJob::dispatch('BTC/USDT')
   │   │
   │   ├─→ Exchange::where('is_active', true)->get()
   │   │
   │   ├─→ Для каждой биржи:
   │   │   ├─→ ExchangeServiceFactory::createFromModel($exchange)
   │   │   ├─→ $service->getTickerPrice('BTC/USDT')
   │   │   │   └─→ HTTP запрос к API биржи
   │   │   └─→ Price::create([...])
   │   │
   │   └─→ Цены сохранены в БД
   │
   └─→ CheckArbitrageJob::dispatch('BTC/USDT')
       │
       ├─→ ArbitrageService::checkArbitrage('BTC/USDT')
       │   │
       │   ├─→ Получить все активные биржи
       │   ├─→ Получить последние цены (не старше 1 минуты)
       │   ├─→ Найти минимальную и максимальную цену
       │   ├─→ Вычислить прибыль
       │   └─→ Если прибыль >= 0.5%, создать Alert
       │
       └─→ Если Alert создан:
           │
           ├─→ User::where('is_active', true)
           │       ->where('alerts_enabled', true)
           │       ->get()
           │
           └─→ Для каждого пользователя:
               └─→ SendTelegramNotificationJob::dispatch($telegramId, $alertId)
                   │
                   ├─→ Alert::find($alertId)
                   ├─→ TelegramBotService::formatArbitrageAlert($alert)
                   ├─→ TelegramBotService::sendMessage($telegramId, $message)
                   └─→ Alert::update(['notified' => true])

Параллельная работа компонентов:

┌─────────────────────┐
│  Queue Worker       │ ← Выполняет Jobs из очереди Redis
│  (php artisan       │
│   queue:work)       │
└─────────────────────┘

┌─────────────────────┐
│  Telegram Bot       │ ← Обрабатывает команды пользователей
│  (php artisan        │
│   telegram:bot)     │
└─────────────────────┘

┌─────────────────────┐
│  Price Fetcher      │ ← Получает цены и проверяет арбитраж
│  (php artisan        │
│   arbitrage:...)    │
└─────────────────────┘

Все три процесса работают одновременно и независимо друг от друга.


База данных

Схема базы данных:

users
├── id (bigint, primary key)
├── telegram_id (string, unique)
├── password_hash (string)
├── is_active (boolean)
├── alerts_enabled (boolean)
├── created_at (timestamp)
└── updated_at (timestamp)

exchanges
├── id (bigint, primary key)
├── name (string, unique)        # Binance, OKX, Bybit
├── api_url (string)             # URL API биржи
├── priority (integer)           # 1 = самый важный
├── is_active (boolean)
├── created_at (timestamp)
└── updated_at (timestamp)

prices
├── id (bigint, primary key)
├── exchange_id (bigint, foreign key → exchanges.id)
├── symbol (string)               # BTC/USDT, ETH/USDT
├── price (decimal 8,2)
├── created_at (timestamp)
└── updated_at (timestamp)

alerts
├── id (bigint, primary key)
├── symbol (string)
├── buy_exchange (string)         # Название биржи
├── sell_exchange (string)
├── buy_price (decimal 8,2)
├── sell_price (decimal 8,2)
├── profit_percent (decimal 4,2)
├── notified (boolean)
├── created_at (timestamp)
└── updated_at (timestamp)

Связи (Relationships):

Exchange → Price (One-to-Many)

  • Одна биржа имеет много цен
  • $exchange->prices - все цены биржи

Price → Exchange (Many-to-One)

  • Много цен принадлежат одной бирже
  • $price->exchange - биржа цены

Пример использования связей:

// Получить все цены биржи Binance
$exchange = Exchange::where('name', 'Binance')->first();
$prices = $exchange->prices;

// Получить биржу, которой принадлежит цена
$price = Price::find(1);
$exchange = $price->exchange;

Как запустить проект

1. Установка зависимостей

composer install

2. Настройка окружения

Скопируйте .env.example в .env:

cp .env.example .env

Отредактируйте .env:

# База данных
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crypto_spread
DB_USERNAME=crypto_user
DB_PASSWORD=your_password

# Redis (для очередей)
REDIS_HOST=127.0.0.1
REDIS_PORT=6379

# Telegram
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
TELEGRAM_BOT_PASSWORD=your_secure_password

3. Создание Telegram бота

  1. Найдите @BotFather в Telegram
  2. Отправьте /newbot и следуйте инструкциям
  3. Скопируйте токен в .env

4. Запуск миграций и сидеров

php artisan migrate
php artisan db:seed

Это создаст таблицы и заполнит их начальными данными (биржи).

5. Запуск сервисов

Откройте 3 терминала:

Терминал 1 - Воркер очередей:

php artisan queue:work redis --tries=3

Терминал 2 - Telegram бот:

php artisan telegram:bot

Терминал 3 - Фетчер цен:

php artisan arbitrage:fetch-prices BTC/USDT --interval=5

6. Использование бота

  1. Найдите вашего бота в Telegram
  2. Отправьте /start
  3. Отправьте /set_password YOUR_PASSWORD (пароль из .env)
  4. Готово! Вы будете получать уведомления об арбитраже

Как добавить новую функциональность

Пример 1: Добавить новую биржу

Шаг 1: Создайте сервис биржи

Создайте файл app/Services/Exchange/KrakenService.php:

<?php

namespace App\Services\Exchange;

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;

class KrakenService implements ExchangeServiceInterface {
    private Client $client;
    private string $baseUrl = 'https://api.kraken.com/0/public';

    public function __construct() {
        $this->client = new Client([
            'timeout' => 10,
            'verify' => true,
        ]);
    }

    public function getTickerPrice(string $symbol): ?float {
        try {
            // Преобразуем BTC/USDT в формат Kraken (XBTUSDT)
            $normalizedSymbol = $this->normalizeSymbol($symbol);
            
            $response = $this->client->get("{$this->baseUrl}/Ticker", [
                'query' => ['pair' => $normalizedSymbol],
            ]);

            $data = json_decode($response->getBody()->getContents(), true);

            // Парсим ответ Kraken (формат может отличаться)
            if (isset($data['result'][$normalizedSymbol]['c'][0])) {
                return (float) $data['result'][$normalizedSymbol]['c'][0];
            }

            return null;
        } catch (GuzzleException $e) {
            Log::error("Kraken API error: " . $e->getMessage());
            return null;
        }
    }

    public function getName(): string {
        return 'Kraken';
    }

    private function normalizeSymbol(string $symbol): string {
        // BTC/USDT → XBTUSDT (специфика Kraken)
        $symbol = str_replace('/', '', $symbol);
        return str_replace('BTC', 'XBT', $symbol);
    }
}

Шаг 2: Добавьте в Factory

Отредактируйте app/Services/Exchange/ExchangeServiceFactory.php:

public static function create(string $exchangeName): ?ExchangeServiceInterface {
    $exchangeName = strtolower($exchangeName);

    switch ($exchangeName) {
        case 'binance':
            return new BinanceService();
        case 'okx':
            return new OKXService();
        case 'bybit':
            return new BybitService();
        case 'kraken':  // ← Добавьте это
            return new KrakenService();
        default:
            return null;
    }
}

Шаг 3: Добавьте биржу в БД

Отредактируйте database/seeders/ExchangeSeeder.php:

$exchanges = [
    // ... существующие биржи
    [
        'name' => 'Kraken',
        'api_url' => 'https://api.kraken.com/0/public',
        'priority' => 4,
        'is_active' => true,
    ],
];

Шаг 4: Запустите сидер

php artisan db:seed --class=ExchangeSeeder

Готово! Теперь система будет получать цены с Kraken.


Пример 2: Добавить новую команду Telegram бота

Шаг 1: Добавьте обработчик в TelegramBotCommand.php

private function handleMessage(array $message): void {
    // ... существующий код
    
    switch ($command) {
        // ... существующие команды
        case '/status':  // ← Добавьте это
            $this->handleStatus($chatId);
            break;
    }
}

// Добавьте новый метод
private function handleStatus(string $chatId): void {
    $user = User::where('telegram_id', $chatId)->first();
    
    if (!$user || !$user->is_active) {
        $this->telegramService->sendMessage(
            $chatId,
            "❌ Please authenticate first using /set_password"
        );
        return;
    }
    
    $alertsCount = Alert::count();
    $activeExchanges = Exchange::where('is_active', true)->count();
    
    $message = "📊 <b>System Status</b>\n\n" .
        "Active exchanges: {$activeExchanges}\n" .
        "Total alerts: {$alertsCount}\n" .
        "Your alerts: " . ($user->alerts_enabled ? "✅ Enabled" : "❌ Disabled");
    
    $this->telegramService->sendMessage($chatId, $message);
}

Теперь пользователи смогут использовать команду /status.


Пример 3: Изменить минимальный процент прибыли

Отредактируйте app/Services/ArbitrageService.php:

class ArbitrageService {
    // Измените значение
    private const MIN_PROFIT_PERCENT = 1.0; // Было 0.5, стало 1.0
    
    // Или сделайте настраиваемым через .env
    private function getMinProfitPercent(): float {
        return (float) config('arbitrage.min_profit_percent', 0.5);
    }
}

Добавьте в config/arbitrage.php (создайте файл):

<?php

return [
    'min_profit_percent' => env('ARBITRAGE_MIN_PROFIT_PERCENT', 0.5),
];

В .env:

ARBITRAGE_MIN_PROFIT_PERCENT=1.0

Часто задаваемые вопросы

Q: Что такое Eloquent?

A: Eloquent - это ORM (Object-Relational Mapping) Laravel. Он позволяет работать с БД через PHP объекты вместо SQL запросов.

// Вместо SQL:
// SELECT * FROM users WHERE telegram_id = '123'

// Eloquent:
$user = User::where('telegram_id', '123')->first();

Q: Что такое Dependency Injection?

A: Это когда Laravel автоматически передает зависимости в конструктор:

// Laravel автоматически создаст TelegramBotService
public function __construct(TelegramBotService $telegramService) {
    $this->telegramService = $telegramService;
}

Q: Как работают очереди (Queues)?

A: Очереди позволяют выполнять задачи асинхронно:

// Задача будет выполнена в фоне (не блокирует выполнение)
FetchPricesJob::dispatch('BTC/USDT');

Воркер очереди (php artisan queue:work) постоянно проверяет очередь и выполняет задачи.

Q: Как добавить логирование?

A: Используйте Log facade:

use Illuminate\Support\Facades\Log;

Log::info("Something happened", ['data' => $data]);
Log::warning("Warning message");
Log::error("Error occurred", ['error' => $exception]);

Логи сохраняются в storage/logs/laravel.log.

Q: Как отладить код?

A: Используйте dd() (dump and die):

dd($variable); // Выведет переменную и остановит выполнение

Или dump() (не останавливает выполнение):

dump($variable);

Q: Как работает автозагрузка классов?

A: Laravel использует Composer autoloader. Классы автоматически загружаются по namespace:

// Файл: app/Services/ArbitrageService.php
namespace App\Services;

// Использование:
use App\Services\ArbitrageService;

Q: Что такое миграции?

A: Миграции - это версионирование схемы БД. Они описывают структуру таблиц в PHP коде.

// Создать таблицу
Schema::create('prices', function (Blueprint $table) {
    $table->id();
    $table->foreignId('exchange_id');
    $table->string('symbol');
    $table->decimal('price', 8, 2);
    $table->timestamps();
});

Q: Как работает конфигурация?

A: Конфигурация хранится в config/ и может быть переопределена через .env:

// config/services.php
'telegram' => [
    'bot_token' => env('TELEGRAM_BOT_TOKEN'),
],

// .env
TELEGRAM_BOT_TOKEN=your_token_here

// Использование:
config('services.telegram.bot_token')

Полезные команды Artisan

# Список всех команд
php artisan list

# Запустить миграции
php artisan migrate

# Откатить последнюю миграцию
php artisan migrate:rollback

# Запустить сидеры
php artisan db:seed

# Очистить кеш
php artisan cache:clear
php artisan config:clear

# Просмотреть логи
tail -f storage/logs/laravel.log

# Войти в Tinker (интерактивная консоль)
php artisan tinker

Заключение

Этот проект демонстрирует основные концепции Laravel:

  • Models - работа с БД
  • Services - бизнес-логика
  • Jobs - асинхронные задачи
  • Commands - консольные команды
  • Dependency Injection - автоматическая передача зависимостей

Если у вас есть вопросы, изучайте код, читайте логи и экспериментируйте!

Удачи в разработке! 🚀