Le crédit agricole reste sous-distribué en Afrique : seulement 5-10 % des producteurs accèdent à des financements formels. Banques traditionnelles refusent (pas de garanties, scoring obsolète). Mais avec mobile money + données satellites + ML, scoring alternatif devient viable. Marché potentiel : 5-15 milliards USD.
TL;DR
- Scoring alternatif basé : mobile money history + données parcelles + météo + comportement remboursement antérieur.
- Stack : Next.js + Python ML pipeline + Mono Connect + satellite Sentinel-2.
- ROI : NPL 3-8 % vs 15-25 % crédit agricole traditionnel.
Sources données scoring
| Source | Indicateur | Poids dans scoring |
|---|---|---|
| Mobile money 12 mois | Volume entrants/sortants, régularité | 30 % |
| Historique remboursement | Crédits passés (cooperative, MFI) | 25 % |
| Données parcelle satellite | NDVI, surface, productivité estimée | 20 % |
| Météo régionale | Stress hydrique anticipé | 10 % |
| Réseau social agri | Coopérative, recommandations | 10 % |
| Démographie | Âge, ancienneté activité | 5 % |
Architecture scoring
`
[Demande crédit producteur]
↓
[Collecte data multi-sources]
├── Mobile money (Mono Connect Wave/MTN)
├── Historique MFI (réseau partenaire)
├── Parcelle GPS + NDVI (satellite)
├── Météo CHIRPS / NASA POWER
└── Profil cooperative
↓
[ML Pipeline Python]
├── Feature engineering
├── XGBoost classifier
├── Risk score 0-1000
└── PD (probability default) 0-1
↓
[Décision : approuvé / refusé / conditionnel]
↓
[Décaissement Wave/MTN]
↓
[Suivi remboursement automatisé]
`
Étape 1 — modèle de données
`prisma
model LoanApplication {
id String @id @default(cuid())
producerId String
amountRequested Int // XOF
durationMonths Int
purpose String // SEEDS / FERTILIZER / EQUIPMENT / WORKING_CAPITAL
status String // SUBMITTED / SCORING / APPROVED / REJECTED / DISBURSED / REPAID / DEFAULTED
riskScore Int? // 0-1000
pdEstimate Float? // 0-1
approvedAmount Int?
approvedRate Float? // % annuel
collateral Json? // si garantie
// Sources data
mobileMoneyData Json?
parcelData Json?
weatherData Json?
cooperativeRefs Json?
decidedAt DateTime?
decidedBy String? // user.id ou "AUTO_ML"
disbursedAt DateTime?
dueDate DateTime?
repaidAt DateTime?
defaultedAt DateTime?
}
`
Étape 2 — collecte mobile money via Mono Connect
`ts
// jobs/collect-mobile-money-data.ts
async function collectMobileMoneyData(producerId: string) {
const producer = await prisma.producer.findUnique({ where: { id: producerId } });
// Producer connecte son Wave/MTN account via Mono Connect
// Voir Open Banking Afrique →
const transactions = await mono.account.transactions(producer.monoAccountId, {
start: addMonths(new Date(), -12).toISOString(),
end: new Date().toISOString(),
});
// Calculer features
const features = {
avgMonthlyInflow: average(byMonth(transactions, 'CREDIT')),
avgMonthlyOutflow: average(byMonth(transactions, 'DEBIT')),
inflowVariability: stdDev(byMonth(transactions, 'CREDIT')),
monthsActive: countDistinctMonths(transactions),
seasonalityScore: detectSeasonality(transactions),
largeTransactionsCount: transactions.filter(t => t.amount > 100000).length,
pendingDebtsRatio: computeDebtRatio(transactions),
};
return features;
}
`
Étape 3 — analyse parcelle satellite
`ts
// lib/satellite-analysis.ts
async function analyzeParcelle(plot: Plot) {
// Sentinel-2 + Google Earth Engine API
const ndviTimeSeries = await fetchNDVITimeSeries({
lat: plot.gpsLat,
lng: plot.gpsLng,
bufferM: 50,
startDate: addYears(new Date(), -2),
endDate: new Date(),
});
return {
avgNDVI: mean(ndviTimeSeries.map(p => p.ndvi)),
ndviTrend: linearRegression(ndviTimeSeries).slope, // positif = sain
productivityEstimate: estimateYield(ndviTimeSeries, plot.productType),
waterStressDays: countWaterStressDays(ndviTimeSeries),
surfaceHa: plot.surfaceHa,
};
Besoin d'un site web professionnel ?
Kolonell crée des sites web qui attirent des clients, optimisés pour le marché sénégalais. Devis gratuit en 2 minutes.
}
`
Étape 4 — ML scoring (Python)
`python
# ml/scoring_model.py
import xgboost as xgb
import pandas as pd
import joblib
def train_model(historical_loans_df):
"""
Entraîne XGBoost sur historique crédits agricoles avec outcomes connus.
"""
features = [
# Mobile money
'mm_avg_monthly_inflow',
'mm_inflow_variability',
'mm_months_active',
'mm_seasonality_score',
# Satellite parcelle
'parcel_avg_ndvi',
'parcel_ndvi_trend',
'parcel_productivity_estimate',
'parcel_surface_ha',
# Historique MFI
'mfi_loans_count',
'mfi_repaid_on_time_ratio',
# Démographie
'producer_age',
'years_farming',
'cooperative_member',
# Météo régional
'rainfall_avg_5y',
'drought_events_5y',
]
X = historical_loans_df[features]
y = historical_loans_df['defaulted'] # 0/1
model = xgb.XGBClassifier(
n_estimators=200,
max_depth=6,
learning_rate=0.05,
)
model.fit(X, y)
joblib.dump(model, 'agri_scoring_v2.joblib')
return model
def predict_pd(features):
"""Prédire probability of default 0-1"""
model = joblib.load('agri_scoring_v2.joblib')
pd_estimate = model.predict_proba([features])[0][1]
risk_score = int((1 - pd_estimate) * 1000)
return {'risk_score': risk_score, 'pd_estimate': pd_estimate}
`
Étape 5 — décaissement et suivi
`ts
async function disburseLoan(applicationId: string) {
const app = await prisma.loanApplication.findUnique({
where: { id: applicationId },
include: { producer: true },
});
// Décaissement via Wave Business B2B
await wavePayout({
receiverMsisdn: app.producer.walletNumber,
amount: app.approvedAmount,
currency: 'XOF',
narration: Crédit agricole #${app.id},
externalId: app.id,
});
// Calendrier remboursement
const installments = generateInstallments(app);
for (const inst of installments) {
await prisma.loanInstallment.create({
data: {
loanId: app.id,
amount: inst.amount,
dueDate: inst.dueDate,
status: 'PENDING',
},
});
}
// Schedule rappels J-7, J-3, J0, J+5
await scheduleReminders(app.id);
}
`
Cas réel — startup CrediTerra Sénégal
Profile : 4 200 producteurs financés en 18 mois.
| Métrique | Valeur |
|---|---|
| Crédits décaissés | 4 200 (4M-150K FCFA chacun) |
| Volume total décaissé | 1.8 milliard FCFA |
| Taux d'intérêt moyen | 22 % annuel (vs banque 18 %, MFI 28-35 %) |
| NPL (Non-Performing Loans) | 5.8 % |
| Marge brute | 14 % |
| Producteurs récurrents | 64 % |
À comparer NPL banque agri tradi : 18-28 %.
Pièges fréquents
- Sur-financer producteur sans capacité — attention au profile risque. ML modèle conservateur au début.
- Décaissement sans suivi — rappels J-7, J-3, J0 = -40 % NPL.
- Cache Wallet désynchronisé — si Wave revoke, Mono perd accès. Re-prompter producer.
- Pas de garantie hybride — assurance récolte (Pula, Acre Africa) couple avec crédit = risque mutualisé.
- Conformité BCEAO — agréement EME ou partenariat banque pour déclarations IMF.
FAQ
Q : Investisseurs intéressés ?
R : Acumen Fund, Mercy Corps Ventures, Sycamore Ventures (Africa AgriTech). Capital 500K-3M USD seed.
Q : Concurrence ?
R : Pula, Apollo Agriculture (KE), Babban Gona (NG), Aerobotics (ZA). Marché Francophone moins saturé.
Q : Réglementation ?
R : BCEAO encadre IMF + EME en UEMOA. Loi 2018-23 SN sur services financiers digitaux.
Conclusion
Crédit agricole digital avec scoring alternatif = opportunité massive Afrique 2026. Investissement 1-3M USD seed pour stack solide. ROI 24-36 mois sur exécution propre + portfolio quality. Impact social mesurable + business viable.
Mohamed Bah
Fondateur, Kolonell
Passionné par le digital et l'entrepreneuriat en Afrique, Mohamed accompagne les entreprises sénégalaises dans leur transformation digitale depuis 2020. Fondateur de Kolonell, il croit que chaque PME mérite une présence en ligne professionnelle et accessible.