Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
18e5df5
Add Binance rates (#1)
m1ndg8mer Mar 31, 2021
f1c799f
Add new Binance currencies (#2)
m1ndg8mer Apr 2, 2021
d9a8ba4
Allow 1 external_rates for Cross calculation (#3)
m1ndg8mer Apr 6, 2021
31c76c9
Add Binance Coin (#4)
m1ndg8mer Apr 30, 2021
388bac4
Money: добавить метод для округления (#6)
m1ndg8mer Aug 31, 2021
58e0e30
Rate source: use transaction instead of locking
m1ndg8mer Oct 4, 2021
fe0b42a
Use self class
m1ndg8mer Oct 5, 2021
9f193e0
Use class name
m1ndg8mer Oct 5, 2021
e264a37
Merge pull request #7 from alfagen/fix/lock
anaumov Oct 11, 2021
adfa692
Добавляем новую крипту: Stellar, Polkadot (#8)
m1ndg8mer Oct 12, 2021
6bda4a0
Doge: increase subunits (#9)
m1ndg8mer Dec 17, 2021
56361ea
ExchangeRate: new validation
m1ndg8mer Dec 19, 2021
8e7d040
Use allias
m1ndg8mer Dec 19, 2021
57a36c2
Use numericality validation
m1ndg8mer Dec 19, 2021
3b7a21e
Merge pull request #10 from alfagen/fix/exchange-rate
anaumov Dec 20, 2021
f39f93b
Новые криптовалюты: Uniswap, Chainlink (#11)
m1ndg8mer Jan 10, 2022
ee9af7e
ExchangeRate: allow to use negative comission
m1ndg8mer Mar 14, 2022
58b5b08
Merge pull request #12 from alfagen/fix/remove-validation
anaumov Mar 15, 2022
9883a0c
Lock → transaction
anaumov May 12, 2022
fdaf7e0
Используем update_attribute для обновления снепшота
anaumov May 12, 2022
0f2ad31
Обновляем только snapshot_id
anaumov May 12, 2022
94a8855
Обновляем снепшот снаружи транзакции
anaumov May 12, 2022
53dbda2
Auto Rates by reserve (#13)
m1ndg8mer Jun 29, 2022
324be6a
Изменение автокурсов в зависимости от базовых курсов направления (#14)
m1ndg8mer Jul 4, 2022
72cd27a
AutoRates: bestchange (#15)
m1ndg8mer Jul 7, 2022
a62391f
RatesWorker: remove logger to save transaction time (#16)
m1ndg8mer Jul 14, 2022
7757716
RatesWorker optimization (#17)
m1ndg8mer Jul 18, 2022
3efe158
Exchange Rate fee: set min value of -9.9 (#18)
m1ndg8mer Aug 11, 2022
d1f0438
RatesWorker: not use transactions (#19)
m1ndg8mer Aug 17, 2022
31d88d5
Use one thread for updating exchange_rates/external_rates (#21)
m1ndg8mer Sep 1, 2022
aed1695
1 thread for gera_external_rates (#22)
m1ndg8mer Sep 5, 2022
eafb83b
Fix error reference
m1ndg8mer Sep 5, 2022
0e2a70e
Not handle duplicated rates error
m1ndg8mer Sep 22, 2022
3a230cd
Auto Comission: prevent value of (0.7..1.4) range (#24)
m1ndg8mer Oct 4, 2022
d7b6afd
Не делать снепшот актуальным, если он уже актуальный
m1ndg8mer Oct 29, 2022
48f059e
Add reload
m1ndg8mer Oct 29, 2022
ffa2248
Не делать снепшот актуальным, если он уже актуальный
m1ndg8mer Oct 29, 2022
372dedd
Не делать снепшот актуальным, если он уже актуальный
m1ndg8mer Oct 30, 2022
f223221
Revoke all changes
m1ndg8mer Oct 30, 2022
dac3e75
Fix snapshot reference
m1ndg8mer Oct 30, 2022
b8a5ee7
Исправил правило обновления снепшота (#25)
anaumov Dec 4, 2022
3c2eebe
Подчищаю обновления курсов валют (#26)
anaumov Dec 8, 2022
ede2270
Доопределил класс ошибки в ExmoFetcher
anaumov Dec 23, 2022
4fc7288
Добавляем монету TON (#27)
m1ndg8mer Jan 20, 2023
c1a4207
Обновлять рейт без рестарта воркера
anaumov Feb 8, 2023
f4c8e2d
Удаляю лишние подчищалки (#28)
anaumov Feb 10, 2023
5245026
Добавляем валюту: Узбекские сумы (UZS) (#29)
m1ndg8mer Mar 7, 2023
6cde605
Autorates: fix divide zero bug (#31)
m1ndg8mer Jun 15, 2023
8f8682c
Апдейт до Rails 6 (#32)
anaumov Jun 22, 2023
1e617e7
Валидация имени платежки с учетом регистра
anaumov Jun 22, 2023
28eb685
Фикс уникальных воркеров (#33)
anaumov Jun 27, 2023
3db8da5
Лочим загрузку курсов во время выполнения
anaumov Jun 27, 2023
2cf66b0
Exmo: временно убрал лок
m1ndg8mer Sep 1, 2023
5766981
Добавляем курсы Азербайджанского маната с ЦБ РФ (#34)
m1ndg8mer Oct 12, 2023
ce17421
Новые валюты: Белорусский рубль, Солана, USDC (#36)
m1ndg8mer Jan 18, 2024
7bce574
Log exchange_rate_updater_worker calls
anaumov Jan 28, 2024
36a46d2
Revert "Новые валюты: Белорусский рубль, Солана, USDC" (#38)
m1ndg8mer Jan 30, 2024
be7d760
Новые валюты: Белорусский рубль, Солана, USDC (без курсов)
m1ndg8mer Jan 30, 2024
782cd68
Вернул курсы Белорусского рубля, Соланы, USDC
m1ndg8mer Jan 30, 2024
0352215
Новый источник курсов: GarantexIO (#39)
m1ndg8mer Jan 31, 2024
8a5e8b6
Доработки по автокурсам (#37)
m1ndg8mer Feb 1, 2024
3b8e931
Промежуток автокурса: 0.05 -> 0.01
m1ndg8mer Feb 3, 2024
4c31b45
Исправил ошибку, когда in/out валюты совпадают
m1ndg8mer Feb 5, 2024
d380104
Автокурсы: возвращать autorate_from, если нету курсов в целевой позиции
m1ndg8mer Feb 16, 2024
8fcaa82
Уменьшил AUTO_COMISSION_GAP; Подкрутил логику (#40)
m1ndg8mer Feb 21, 2024
27e288a
Фикс нотификации в багснаг
anaumov Feb 21, 2024
f167c7f
Обновил источник курсов Bitfinex (#41)
m1ndg8mer Feb 22, 2024
ed045b2
Bitfinex rates worker: убрал лок
m1ndg8mer Mar 6, 2024
9025a53
Добавил метод alikassa_round: 1 точка после запятой
m1ndg8mer Mar 13, 2024
3a2d81e
Add Turkish Lira, Matic (#42)
m1ndg8mer Apr 8, 2024
a892c40
Комиссия: разрешать диапазон 0.7..1.4 некоторым платежкам
m1ndg8mer May 24, 2024
35d971b
Убрал лок для CurrencyRatesWorker
m1ndg8mer May 31, 2024
90f5d3c
Вернул лок для CurrencyRatesWorker
m1ndg8mer Jun 1, 2024
533638b
Новый источник курсов: ByBit (#43)
m1ndg8mer Jun 19, 2024
ecdb4a2
ByBit: зеркальные курсы (#44)
m1ndg8mer Jun 20, 2024
351e690
Уменьшил к-во вызовов CurrencyRateWorker
m1ndg8mer Jun 20, 2024
184fb54
Не отправлять ошибку в багснеп, если курс не найден
m1ndg8mer Jun 26, 2024
88d2b75
AutoRates: fix position_from param
m1ndg8mer Jun 28, 2024
5a61b04
Правки по автокурсам
m1ndg8mer Jul 4, 2024
122ad63
Новый источник курсов: Trustee (#46)
m1ndg8mer Aug 1, 2024
7c6533d
Новый источник курсов: Cryptomus (#47)
m1ndg8mer Aug 9, 2024
0b852d9
Отключил ограничение 0.7-1.4 для всех направлений
m1ndg8mer Sep 11, 2024
0a99367
Автокурсы: кейз, когда комиссия минусовая
m1ndg8mer Sep 12, 2024
794e5c0
Автокурсы: баг с минусовыми комиссиями
m1ndg8mer Sep 13, 2024
5e860cc
Конфигурации плавающего курса (#48)
m1ndg8mer Oct 3, 2024
0055ae4
Сбор логов по exchange_rates (#49)
m1ndg8mer Nov 27, 2024
fb3eae4
собираем логи в модель
m1ndg8mer Nov 27, 2024
a7179f2
Доработка по воркеру
m1ndg8mer Nov 29, 2024
02ca24d
Уведомление второго столбца (#50)
m1ndg8mer Dec 5, 2024
d7812c1
DirectionsRatesWorker: remove locks
m1ndg8mer Dec 10, 2024
7f64c6c
DirectionsRatesWorker: add until_executed lock
m1ndg8mer Dec 10, 2024
0241cc1
Доработки DirectionsRatesWorker
m1ndg8mer Dec 11, 2024
d680a67
Вынес maxamount в модель
m1ndg8mer Dec 16, 2024
c21ed67
Вынес minamount в модель
m1ndg8mer Dec 16, 2024
19e548b
Crypromus: бага с рублями
m1ndg8mer Feb 7, 2025
e242e8e
Cryptomus бага с рублями #2
m1ndg8mer Feb 7, 2025
45ca82e
Cryptomus бага с рублями #3
m1ndg8mer Feb 7, 2025
1cb89bd
Новая валюта: Тайский Бат (#54)
m1ndg8mer Feb 26, 2025
ddfc4ae
Уменьшил к-во записей на странице external_rate_snapshots
m1ndg8mer Mar 24, 2025
01b9852
Новый источник курсов: FF (#55)
m1ndg8mer Mar 26, 2025
445cb30
Новая валюта: Индонезийская Рупия (#56)
m1ndg8mer Mar 27, 2025
fe3c69f
Комиссия может быть < -10%
m1ndg8mer Apr 1, 2025
10ad584
ExchangeRate: новый скоуп
m1ndg8mer May 16, 2025
57df85f
Трекаем обновление ExchangeRate (#57)
anaumov May 24, 2025
e7f4143
Ускоряем обновление exchange_rates
anaumov Jun 15, 2025
4018302
Выставлять позицию ОТ, если выбран курс с запасом
m1ndg8mer Jul 25, 2025
6512806
Фикс автокурсом
m1ndg8mer Aug 4, 2025
ebe684a
Если есть несовпадения по настройкам - выставляем по Курс от
m1ndg8mer Aug 12, 2025
7341320
Модель exchange_rate_limit (#58)
anaumov Sep 13, 2025
a9d1cfb
Првязка exchange_rate_limit к exchange_rate
anaumov Sep 14, 2025
d5841e8
Оптимизация геры (#59)
m1ndg8mer Oct 14, 2025
47fa470
f
m1ndg8mer Oct 20, 2025
b0d2ff8
f
m1ndg8mer Oct 20, 2025
e569b86
Добавил юань
m1ndg8mer Oct 21, 2025
76a8e83
Добавил юань в CbrRatesWorker
m1ndg8mer Oct 21, 2025
1f04791
Не обновлять глобальные курсы после апдейта exchange_rate
m1ndg8mer Oct 31, 2025
17fe6dc
New currencies: INR, AVAX
m1ndg8mer Nov 19, 2025
c59962a
AUTO_COMISSION_GAP: 0.01 -> 0.001
m1ndg8mer Dec 8, 2025
86d894f
AUTO_COMISSION_GAP: 0.001 -> 0.0001
m1ndg8mer Dec 8, 2025
e35b770
feat: Улучшить алгоритм автокурса - занимать позицию в диапазоне (#69)
dapi Dec 24, 2025
00e0f42
fix: Добавить raise для неизвестного calculator_type и документацию в…
dapi Dec 24, 2025
97c7fa2
chore: Добавить Makefile и docker-compose.yml для разработки
dapi Dec 24, 2025
65021b9
Add ./doc
dapi Dec 25, 2025
7846c5c
ADd CLAUDE.md
dapi Dec 25, 2025
339c3b3
Update doc
dapi Dec 25, 2025
09db5cf
Update doc/autorotate
dapi Dec 25, 2025
b4eab20
test: Добавить тесты UC-5 для варианта A (autorate_from при несовпаде…
dapi Dec 25, 2025
0e31c8a
Add .ruby-version and mise.toml
dapi Dec 25, 2025
c334098
fix: Округление комиссии до 4 знаков после запятой (#75)
dapi Dec 25, 2025
1631358
feat: UC-12 — не вычитать GAP при position_from=1 и одинаковых курсах…
dapi Dec 26, 2025
d76a8e2
debug: Добавить подробное логирование в PositionAware калькулятор
dapi Dec 29, 2025
38cdee3
chore: Bump version to 0.4.2
dapi Dec 29, 2025
e9ad382
feat: UC-12 — обобщить should_skip_gap? для любого position_from
dapi Dec 29, 2025
19129d0
fix: Исправить значение GAP в тестах с 0.001 на 0.0001
dapi Dec 29, 2025
2a93808
chore: Версия 0.4.4
dapi Dec 29, 2025
330e031
fix: Критические исправления из PR review
dapi Dec 30, 2025
27c90d7
Merge pull request #76 from alfagen/feature/69-position-aware-autorat…
dapi Dec 30, 2025
d787ff1
Change autorate debug logging from debug to info level
dapi Jan 4, 2026
e597c2d
chore: Изменить уровень логирования PositionAware с info на warn
dapi Jan 4, 2026
a151b27
fix: Simplify anomaly detection - UC-9 cancelled, UC-13 added
dapi Jan 4, 2026
4fcf06d
feat: UC-14 — fallback на первую целевую позицию при отсутствии rate_…
dapi Jan 4, 2026
6e2ca29
fix: Исправления из PR review для UC-14
dapi Jan 4, 2026
fc30070
ignore .claude/settings.local.json
dapi Jan 4, 2026
f83d546
Update Gemfile.lock
dapi Jan 4, 2026
36e16ae
fix: Исправления из второго PR review
dapi Jan 4, 2026
767f179
Add .worktrees to gitignore
dapi Jan 4, 2026
db79c95
fix: Исправления из третьего PR review
dapi Jan 4, 2026
c27b2e4
fix: Add nil safety to base calculator and fix calculator_type valida…
dapi Jan 4, 2026
57f044b
chore: Add missing UC tests and update documentation
dapi Jan 4, 2026
f94143d
fix: UC-14 — ВСЕГДА использовать курс первой целевой позиции при rate…
dapi Jan 4, 2026
1a5097f
fix: PR review исправления для UC-14
dapi Jan 4, 2026
6359c74
fix: PR review исправления для UC-14 (второй раунд)
dapi Jan 4, 2026
ba054e7
Update CLAUDE.md
dapi Jan 4, 2026
46c6356
fix: Финальная очистка PR — удаление мёртвого кода UC-9
dapi Jan 4, 2026
65bc5dc
fix: PR review — fail fast для nil значений, восстановление after_commit
dapi Jan 4, 2026
7f512cd
fix: Откатить after_commit + добавить логирование пустых rates
dapi Jan 5, 2026
9b4cc44
Merge branch 'legacy' into feature/83-position-aware-anomalous-fallback
dapi Jan 5, 2026
903d605
Merge pull request #85 from alfagen/feature/83-position-aware-anomalo…
dapi Jan 5, 2026
d004181
chore: Release v0.5.0
dapi Jan 5, 2026
967e119
Update CLAUDE.md
dapi Jan 5, 2026
d565bce
fix(issue-2291): allow same-to-same payment system directions
dapi Mar 19, 2026
f690c77
Merge pull request #96 from alfagen/fix/2300-same-to-same
dapi Mar 19, 2026
6facbd3
test(PIR-076): add regression test for same-to-same direction in avai…
dapi Mar 19, 2026
776f93f
Merge pull request #97 from alfagen/fix/2300-same-to-same
dapi Mar 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ spec/dummy/tmp/
*.log
.yardoc/
.byebug_history
.claude/settings.local.json
.worktrees
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.7.8
210 changes: 210 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Gera is a Rails engine for generating and managing currency exchange rates for crypto changers and markets. It collects rates from external sources, builds currency rate matrices, and calculates final rates for payment systems with commissions.

## Core Architecture

### Rate Flow Hierarchy
1. **ExternalRate** - Raw rates from external sources (EXMO, Bitfinex, Binance, CBR, etc.)
2. **CurrencyRate** - Basic currency rates calculated from external rates using different modes (direct, inverse, cross)
3. **DirectionRate** - Final rates for specific payment system pairs with commissions applied
4. **ExchangeRate** - Configuration for commissions between payment systems

### Key Models
- **RateSource** - External rate providers with STI subclasses (RateSourceExmo, RateSourceBitfinex, etc.)
- **PaymentSystem** - Payment systems with currencies and commissions
- **CurrencyPair** - Utility class for currency pair operations
- **Universe** - Central repository pattern for accessing rate data

### Worker Architecture
- **RatesWorker** concern for fetching external rates
- Individual workers for each rate source (ExmoRatesWorker, BitfinexRatesWorker, etc.)
- **CurrencyRatesWorker** - Builds currency rate matrix from external rates
- **DirectionsRatesWorker** - Calculates final direction rates with commissions
- **CreateHistory_intervalsWorker** - Aggregates historical data

## Development Commands

### Running Tests
```bash
# Run all tests
bundle exec rake spec

# Run specific test file
bundle exec rspec spec/models/gera/currency_rate_spec.rb

# Run with focus
bundle exec rspec --tag focus
```

### Building and Development
```bash
# Install dependencies
bundle install

# Run dummy app for testing
cd spec/dummy && rails server

# Generate documentation
bundle exec yard

# Clean database between tests (uses DatabaseRewinder)
```

### Code Quality
```bash
# Lint code
bundle exec rubocop

# Auto-correct linting issues
bundle exec rubocop -a
```

## Configuration

Create `./config/initializers/gera.rb`:
```ruby
Gera.configure do |config|
config.cross_pairs = { kzt: :rub, eur: :rub }
config.default_cross_currency = :usd
end
```

## Key Business Logic

### Rate Calculation Modes
- **direct** - Direct rate from external source
- **inverse** - Inverted rate (1/rate)
- **same** - Same currency (rate = 1)
- **cross** - Calculated through intermediate currency

### Supported Currencies
RUB, USD, BTC, LTC, ETH, DSH, KZT, XRP, ETC, XMR, BCH, EUR, NEO, ZEC

### External Rate Sources
- EXMO, Bitfinex, Binance, GarantexIO
- Russian Central Bank (CBR)
- Manual rates and FF (fixed/float) sources

## Testing Notes

- Uses dummy Rails app in `spec/dummy/`
- Factory Bot for test data in `factories/`
- VCR for HTTP request mocking
- Database Rewinder for fast test cleanup
- Sidekiq testing inline enabled

### Запуск изолированных тестов автокурсов

Для тестов автокурсов (PositionAware, Legacy калькуляторы) используются изолированные тесты,
которые не загружают Rails и spec_helper. Это позволяет быстро тестировать логику без полной
загрузки приложения.

```bash
# Переименовать .rspec чтобы не загружался spec_helper
mv .rspec .rspec.bak

# Запустить изолированные тесты
mise exec -- bundle exec rspec spec/services/gera/autorate_calculators/isolated_spec.rb --no-color

# Вернуть .rspec обратно
mv .rspec.bak .rspec
```

Или используйте Makefile (требует БД):
```bash
make test # запускает isolated_spec.rb и exchange_rate_spec.rb
```

**Важно:** Файл `isolated_spec.rb` самодостаточен и содержит все необходимые стабы для Gera модуля.

## File Organization

- `app/models/gera/` - Core domain models
- `app/workers/gera/` - Background job workers
- `lib/gera/` - Core engine logic and utilities
- `lib/builders/` - Rate calculation builders
- `spec/` - Test suite with dummy app


## Серверы и логи

### Stage сервер

На stage сервере логи находятся тут:

```bash
scp kassa@89.248.193.193:/home/kassa/admin.kassa.cc/current/log/* .
```

### Production сервер

```bash
ssh kassa@185.132.176.44
cd /home/kassa/admin.kassa.cc/current/log
```

## Логи калькулятора PositionAware

Калькулятор `PositionAwareCalculator` логирует с тегом `[PositionAware]` на уровне WARN.

### Команды для анализа логов

```bash
# SSH на production
ssh kassa@185.132.176.44
cd /home/kassa/admin.kassa.cc/current/log

# Все логи PositionAware (последние записи)
grep -i 'PositionAware' production.log | tail -100

# Финальные результаты расчётов
grep 'FINAL RESULT' production.log | grep PositionAware | tail -50

# Пустые target rates (edge case когда мало курсов)
grep 'Target position rates.*\[\]' production.log

# Случаи когда не найден rate_above
grep 'NO rate_above found' production.log | tail -50

# Полный контекст одного расчёта (10 строк до и после FINAL)
grep -B10 -A2 'FINAL RESULT' production.log | grep PositionAware | tail -100
```

### Структура логов калькулятора

```
[PositionAware] START position_from=X position_to=Y # Начало расчёта
[PositionAware] autorate_from=A autorate_to=B # Границы авторейта
[PositionAware] Filtered rates count: N, our_exchanger_id: 522
[PositionAware] Target position rates [X..Y]: [...] # Курсы на целевых позициях
[PositionAware] Target rate: Z # Целевой курс
[PositionAware] calculate_adaptive_gap: ... # Расчёт GAP
[PositionAware] adjust_for_position_above: ... # Корректировка
[PositionAware] FINAL RESULT: X.XXXX # Финальный результат
```

### Особенности интерпретации

- **Отрицательные комиссии** (FINAL RESULT: -0.888) - это нормально
- **find_non_anomalous_rate_above: result = nil** - часто встречается, не аномалия
- **Пустые Target position rates []** - когда настроенная позиция > количества курсов

### Ключевые файлы калькулятора

```bash
# Поиск по имени класса
grep -r "PositionAware" --include="*.rb" .

# Калькулятор вызывается из:
# gera/app/models/gera/exchange_rate.rb:162 - метод rate_comission_calculator
```

# Requirements Management

- **spreadsheet_id:** 1bY_cH5XpuO47qnPsYEdxjkQpwvPNYXHAms_ohkca15A
- **spreadsheet_url:** https://docs.google.com/spreadsheets/d/1bY_cH5XpuO47qnPsYEdxjkQpwvPNYXHAms_ohkca15A
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
# development dependencies will be added by default to the :development group.
gemspec

gem 'rails', '~> 5.2.2.1'
gem 'rails', '~> 6.0.6'
gem 'dapi-archivable', '~> 0.1.2', require: 'archivable'
gem 'active_link_to', github: 'BrandyMint/active_link_to'
gem 'noty_flash', github: 'BrandyMint/noty_flash'
Expand Down
Loading